In FirebirdSql, how to return exception message from procedure

Unfortunately you will need to do that at the client side, as it is currently not possible to obtain this in PSQL. There is a feature request in the Firebird tracker, which has been implemented for Firebird 4, which is expected to be released in 2019.

See Firebird 4 Beta 2 release notes, section System Function RDB$ERROR() (warning: link might break with the next or GA release):

The function RDB$ERROR() takes a PSQL error context as input and returns the specific context of the active exception. Its scope is confined to the context of the exception-handling block in PSQL. Outside the exception handling block, RDB$ERROR always contains NULL.

The type of the return value depends on the context.

Syntax Rules

RDB$ERROR ( context )
context ::= { GDSCODE | SQLCODE | SQLSTATE | EXCEPTION | MESSAGE }

[..]

Example

BEGIN
  ...
WHEN ANY DO
  EXECUTE PROCEDURE P_LOG_EXCEPTION(RDB$ERROR(MESSAGE));
END