bin/coff: promote globals in code sections to FUNC

COFF C_EXT (external/global) symbols carry their function-or-not
status in two places: the DTYPE field of n_type (the ISFCN bit), and
implicitly by the section they live in. The existing code only
honoured the DTYPE bit:

  ptr->type = DTYPE_IS_FUNCTION(s->n_type) || !strcmp(name, "main")
      ? RZ_BIN_TYPE_FUNC_STR : RZ_BIN_TYPE_UNKNOWN_STR;

C and C++ compilers set the ISFCN bit when emitting object code, so
this works for compiled output. But assembler-emitted globals -- TI's
asm55p / cl55, the GNU GAS COFF backend on legacy targets, and any
hand-written .s -- often leave n_type at zero. Every assembly symbol
then comes back as RZ_BIN_TYPE_UNKNOWN_STR, and 'aaa' has no way to
distinguish a function from a data label. Concrete example: with TI
asm55p output for the C55x+ test corpus, none of the eight .global
labels in 03_branches_calls.s (_short_ret, _short_branch, _short_call,
...) were promoted to functions, so analysis only found those
reachable by following control flow from a hard-coded entry.

Add a section-flag fallback: if the symbol's containing section has
COFF_SCN_CNT_CODE set (i.e. it's a .text / code section), the symbol
is a function. This keeps the DTYPE check as the primary signal but
fills the gap on assembler output.

Verified with TI C55x+ .obj files: all .global labels now appear as
RZ_BIN_TYPE_FUNC_STR and are picked up by 'aaa'. No regression on
the standard COFF test suite (Windows i386/amd64 .obj from compiled
C output).
This commit is contained in:
Anton Kochkov 2026-05-27 00:22:21 +00:00 committed by NOT XVilka
parent 88a4121d70
commit 64c1cad7e5
2 changed files with 14 additions and 2 deletions

View file

@ -107,7 +107,19 @@ static bool coff_fill_bin_symbol(RzBin *rbin, struct rz_bin_coff_obj *bin, size_
} else {
ptr->bind = RZ_BIN_BIND_GLOBAL_STR;
}
ptr->type = (DTYPE_IS_FUNCTION(s->n_type) || !strcmp(coffname, "main"))
/* DTYPE_IS_FUNCTION checks the n_type ISFCN bit, which C and
* C++ compilers set on function symbols. Assembler-emitted
* globals (TI asm55/cl55, GAS COFF output) don't always set
* that bit, but they're nonetheless functions when their
* containing section has CNT_CODE. Promote them so analysis
* (aa) sees real functions instead of unknown globals.
*
* The 'main' name override predates this and stays as the
* last-resort fallback for files where neither the type bit
* nor section flags are reliable. */
ptr->type = (DTYPE_IS_FUNCTION(s->n_type) ||
(sc_hdr && (sc_hdr->s_flags & COFF_SCN_CNT_CODE)) ||
!strcmp(coffname, "main"))
? RZ_BIN_TYPE_FUNC_STR
: RZ_BIN_TYPE_UNKNOWN_STR;
break;

View file

@ -295,7 +295,7 @@ cyclomatic-cost: 0
cyclomatic-complexity: 1
loops: 0
bits: 16
type: fcn
type: sym
num-bbs: 1
edges: 0
end-bbs: 1