1

I'm playing with a pe32 file. With is, Some of my symbols say GLOBAL others say NONE,

006 0x00027514 0x100428114 GLOBAL   FUNC    0 k.exe_asdf
....
002 0x0002a808 0x10042c008   NONE   FUNC    0 imp.foo.dll_bar

Are the only two options GLOBAL and NONE? Where can I find the output definition of this screen. If I run the same executable under objdump -t it just shows

./k.exe:     file format pei-x86-64

SYMBOL TABLE:
no symbols

nm also shows no symbols. I'm guessing though that radare2 is just better working with pe32+ files?

1

PE Binding

"GLOBAL" and "NONE" are values of the "Bind" column in radare2's symbol table. As @blabb correctly described, whenever you look at the "Exports" through radare2 you'll see the value "GLOBAL" assigned to ptr->bind and you'll see "NONE" assigned to each import. The thing is, that this is only relevant for PE files and I'll soon explain it deeper. For now, let's look at the implemented code in radare2.

@blabb mentioned that you can easily spot this in the code, that's true. Here's how the implementation of bind is for PE exports:

if ((symbols = PE_(r_bin_pe_get_exports)(bf->o->bin_obj))) {
        for (i = 0; !symbols[i].last; i++) {
            if (!(ptr = R_NEW0 (RBinSymbol))) {
                break;
            }
            ptr->name = strdup ((char *)symbols[i].name);
            ...
            ptr->bind = r_str_const ("GLOBAL");
            ptr->type = r_str_const ("FUNC");
            ptr->size = 0;
            ...
            ...

You can see that ptr->bind is unconditionally assigned to be "GLOBAL".

That's how the implementation of bind is looking like for PE import:

if ((imports = PE_(r_bin_pe_get_imports)(bf->o->bin_obj))) {
        for (i = 0; !imports[i].last; i++) {
            if (!(ptr = R_NEW0 (RBinSymbol))) {
                break;
            }
            ...
            ptr->name = r_str_newf ("imp.%s", imports[i].name);
            ptr->bind = r_str_const ("NONE");
            ptr->type = r_str_const ("FUNC");
            ptr->size = 0;
            ...
            ...

Again, it is unconditionally assigned to "NONE".


Symbol Binding

Symbol binding is a subject that thoroughly was already answered by @SYS_V in this incredibly good answer.

To quote from his answer:

There must be a way for the link editor (ld) to determine the scope of a symbol during link-time. In other words, symbol binding allows the link editor to differentiate between symbols visible only within a particular file being linked (local scope) vs. symbols that can be referenced from within functions located in other files (global scope).

For ELF files, GLOBAL binding means the symbol is visible outside the file. LOCAL binding is visible only in the file. WEAK is like global, the symbol can be overridden.

There are many more binding values for ELF as you can see in this table:

+------------+-------+
|    Name    | Value |
+------------+-------+
| STB_LOCAL  |     0 |
| STB_GLOBAL |     1 |
| STB_WEAK   |     2 |
| STB_LOOS   |    10 |
| STB_HIOS   |    12 |
| STB_LOPROC |    13 |
| STB_HIPROC |    15 |
+------------+-------+

And radare2 implemented it as well in fill_symbol_bind_and_type:

switch (ELF_ST_BIND(sym->st_info)) {
case STB_LOCAL:  s_bind ("LOCAL"); break;
case STB_GLOBAL: s_bind ("GLOBAL"); break;
case STB_WEAK:   s_bind ("WEAK"); break;
case STB_NUM:    s_bind ("NUM"); break;
case STB_LOOS:   s_bind ("LOOS"); break;
case STB_HIOS:   s_bind ("HIOS"); break;
case STB_LOPROC: s_bind ("LOPROC"); break;
case STB_HIPROC: s_bind ("HIPROC"); break;
default:         s_bind ("UNKNOWN");
}

Further reading

I highly recommend @SYS_V's answer for more information. You can also read more about Symbol Resolution here and you can find more information about Symbol visibility in this link.

1

exported functions in a binary are denoted by GLOBAL imported function in a binary are denoted by NONE

:\>rabin2  -i ..\..\miscinfo\Debug\tzinfo.dll | grep -i Mod
003 0x10016008 NONE FUNC KERNEL32.dll_GetModuleFileNameA
011 0x10016028 NONE FUNC KERNEL32.dll_GetModuleHandleW
009 0x10016088 NONE FUNC VCRUNTIME140D.dll___vcrt_GetModuleFileNameW
010 0x1001608c NONE FUNC VCRUNTIME140D.dll___vcrt_GetModuleHandleW

:\>rabin2  -E ..\..\miscinfo\Debug\tzinfo.dll
[Exports]
000 0x0000bb80 0x1000c780 GLOBAL   FUNC    0 tzinfo.dll_DebugExtensionInitialize
001 0x0000bc10 0x1000c810 GLOBAL   FUNC    0 tzinfo.dll_DebugExtensionNotify
002 0x0000bbb0 0x1000c7b0 GLOBAL   FUNC    0 tzinfo.dll_DebugExtensionUninitialize
003 0x0000bad0 0x1000c6d0 GLOBAL   FUNC    0 tzinfo.dll_help
004 0x00000670 0x10001270 GLOBAL   FUNC    0 tzinfo.dll_tzinfo

btw you can get the source for radare and grep through the src to find most of the answers

>grep -r "\"GLOBAL\"" *
libr/bin/format/elf/elf.c:      case STB_GLOBAL: s_bind ("GLOBAL"); break;
libr/bin/p/bin_mach0.c:                 "LOCAL":"GLOBAL");
libr/bin/p/bin_pe.c:                ptr->bind = r_str_const ("GLOBAL");
libr/core/bin.c:        return (strcmp (s->bind, "GLOBAL") == 0);
shlr/java/class.c:                      sym->bind = r_str_const ("GLOBAL");
shlr/java/class.c:                      sym->bind = r_str_const ("GLOBAL");

and actual srccode

>grep -r -B 10 -A 5 "\"GLOBAL\""  .\libr\bin\p\bin_pe.c
        if (!(ret = r_list_new ()))
                return NULL;
        ret->free = free;
        if ((symbols = PE_(r_bin_pe_get_exports)(arch->o->bin_obj))) {
                for (i = 0; !symbols[i].last; i++) {
                    if (!(ptr = R_NEW0 (RBinSymbol)))
                        break;
                    ptr->name = strdup ((char *)symbols[i].name);
                    ptr->forwarder = r_str_const ((char *)symbols[i].forwarder);
                    //strncpy (ptr->bind, "NONE", R_BIN_SIZEOF_STRINGS);
                    ptr->bind = r_str_const ("GLOBAL");
                    ptr->type = r_str_const ("FUNC");
                    ptr->size = 0;
                    ptr->vaddr = symbols[i].vaddr;
                    ptr->paddr = symbols[i].paddr;
                    ptr->ordinal = symbols[i].ordinal;
-1

Though I'm not sure, I think NONE means IMPORTED as the Symbol list of the NONE can be reproduced with rabin -i where -i means show imported symbols,

2 0x10042c008    NONE    FUNC NETAPI32.dll_NetUserModalsSet

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.