Search code examples
binarysymbolselfpowerpcida

PowerPC64 imports rename


Compiling a .c file using powerpc64-linux-gnu-gcc yields the following binary:

.text:00000000100007F4 # .rename _00000017.plt_call.memcpy__GLIBC_2.3, "_00000017.plt_call.memcpy@@GLIBC_2.3"
.text:00000000100007F4
.text:00000000100007F4 # =============== S U B R O U T I N E =======================================
.text:00000000100007F4
.text:00000000100007F4 # void *00000017_plt_call_memcpy__GLIBC_2_3(void *dest, const void *src, size_t n)
.text:00000000100007F4                         _00000017.plt_call.memcpy__GLIBC_2.3:
.text:00000000100007F4 .set arg_28,  0x28
.text:00000000100007F4
.text:00000000100007F4 std       r2, arg_28(r1)
.text:00000000100007F8 ld        r12, (memcpy_plt - 0x10027F00)(r2) # memcpy
.text:00000000100007FC mtctr     r12
.text:0000000010000800 ld        r2, (qword_10020158 - 0x10027F00)(r2)
.text:0000000010000804 bctr
.text:0000000010000804 # End of function _00000017.plt_call.memcpy__GLIBC_2.3

I can't understand where the .rename _00000017.plt_call.memcpy__GLIBC_2.3 comes from, and why is it renamed from just being memcpy?

Example to the code that gives this result:

int main()
{
    char* buf = (char*)calloc(25, sizeof(char));
    char* buf1 = (char*)calloc(25, sizeof(char));
    memcpy(buf, buf1, 25);
}

Solution

  • This GLIBC_2.3 stuff is introduced during linking (the compiler doesn't know anything about your Glibc version). And the .rename comments in the listing are an IDA artifact. (Does IDA documentation tell anything about them?)

    The @ signs you see indicate symbol versions, @@ designating the default version to which external (to Glibc, in this case) references to this symbol are bound.

    The linker supports symbol versions when using ELF. Symbol versions are only useful when using shared libraries. The dynamic linker can use symbol versions to select a specific version of a function when it runs a program that may have been linked against an earlier version of the shared library.

    So the decision as to which symbol a reference in your program will be bound to is ulimately made at load time by ld.so. Maybe this is what .rename means.

    With the GNU toolchain the binding decision can actually be delayed until run time. On my platform (x86_64-linux-gnu) memcpy is an IFUNC. You can check whether that's the case for you by looking at glibc's symbols like this readelf -s /lib/libc.so.6 | grep IFUNC.*memcpy. In theory, though, IDA wouldn't know the ultimate destination without running the code, so ifuncs are likely irrelevant here. You can test other libc functions that are not ifuncs for the sake of a cleaner experiment though.