How can my C code find the symbol corresponding to an address at run-time (in Linux)?
Asked Answered
M

3

7

Given a function or variable run-time address, my code needs to find out the name and, if it's a variable, type information of the symbol. Or at least provide enough information for later, off-line extraction of the name (and type info).

It is Linux code and it is assumed debug information is available.

I tried to look into the ELF file format, binutils and all but the subject is huge, so I was hoping somebody can help me narrow the scope.

I can see the following types of solutions:

  • find the range of the code/data segments of the modules currently loaded in memory - HOW TO DO THAT ?. Save the address's module and segment name and offset in it's segment. Off-line then use binutils to find the symbol in the module's debug info - again, HOW TO DO THAT?

  • use some API/system services I do not know of to find the symbol and info at run-time - HOW?

Thank you in advance.

Martinamartindale answered 30/6, 2015 at 20:51 Comment(7)
There are no any symbols in runtime.Arillode
You could have a look at procfs.Frigidarium
Are you looking for a program to report on aspects of its own layout, or to examine a different program's layout?Persuasion
You'll probably want to link the main executable with -rdynamicShankle
Olaf, I looked at procfs and the only thing that looked to me related is the ELF interpreter info in auxv. Is that what you referred to? If so, can you point me to doc for the info - the man page says only that they are pair of integers. ThanksMartinamartindale
John, my code is a shared lib that is linked in by 3rd party programs and must present run-time info about them, So it is about my own process but I have no control or knowledge of the code itself. I just receive addresses and try to present them in a form that makes sense to humans. ThanksMartinamartindale
I want to apologize to all who answered/commented for the long silence. I've got sucked up in an emergency and did not check back the site. I am grateful for the effort. Thank youMartinamartindale
A
10

GNU libc provides a dladdr function for this exact purpose. However, it only works on functions, not variables.

   #define _GNU_SOURCE         /* See feature_test_macros(7) */
   #include <dlfcn.h>

   int dladdr(void *addr, Dl_info *info);

   The  function  dladdr()  takes  a function pointer and tries to resolve
   name and file where it  is  located.   Information  is  stored  in  the
   Dl_info structure:

       typedef struct {
           const char *dli_fname;  /* Pathname of shared object that
                                      contains address */
           void       *dli_fbase;  /* Address at which shared object
                                      is loaded */
           const char *dli_sname;  /* Name of symbol whose definition
                                      overlaps addr */
           void       *dli_saddr;  /* Exact address of symbol named
                                      in dli_sname */
       } Dl_info;

   If no symbol matching addr could be found, then dli_sname and dli_saddr
   are set to NULL.

   dladdr() returns 0 on error, and nonzero on success.

Of course, usually I do this sort of thing from gdb, not within the program itself.

Aletaaletha answered 30/6, 2015 at 21:52 Comment(5)
Are you sure that dladdr does not work on global variables? I believe it should (but never tested).Shankle
@BasileStarynkevitch I'm not sure sure, I did a minimal test with gdb instead of actually writing a program, and it failed in that context.Aletaaletha
@011c, that was my first try but I always get a failure (not zero) from dladdr. I pass in the address of a function, and the code is compiled for debug. What am I missing? Dl_info info; if (!dladdr(threadFuncAddress, &info) && info.dli_sname) { strncpy(szName, info.dli_sname, TRACED_THREAD_NAME_SIZE); szName[TRACED_THREAD_NAME_SIZE - 1] = 0; } Martinamartindale
This looks like it would only work on symbols from a shared lib resolve at runtime.Grandiloquence
@Grandiloquence You may wish to read the ld man page, particularly about --gc-keep-exported and --export-dynamic. At runtime, the executable (including any static libraries) is basically no different than a shared library.Aletaaletha
R
2

What you want to look at is the Binary File Descriptor library specifically the symbol handling functions. libbfd provides a common set of functions for manipulating and reading various object formats. It does this by providing an abstract view of object files and then has specific back ends to handle the details of specific object types and architectures. ELF file formats are supported as is most likely the architecture you want to use.

I don't find libbfd difficult to use but I am always open to alternatives and libelf is another one. You will probably want to look at the gelf_getsym function specifically.

Remainderman answered 30/6, 2015 at 21:45 Comment(2)
BFD is exceedingly difficult to use, and is not recommended for parsing ELF files or DWARF debug info.Kuwait
@esm I think BFD is what binutils uses. But binutils, BFD, libelf, etc all operate on files and as such I assume they use relative addresses. At run-time I get a session-specific virtual memory address that I need to convert to a relative one in order to be able to look for it in the file. Is my understanding correct?Martinamartindale
T
0

C is a fully-compiled language. The names and types and other info about variables are generally discarded in the compilation process.

An exception is that most compilers will produce an executable with debugging information included, so that a live debugger has access to this information. This info is totally OS-specific, and even compiler-specific, and might even be in parts of memory not accessible to the program.

Thumbsdown answered 30/6, 2015 at 21:35 Comment(3)
OP said debug information is available, so I guess it is possible one way or another. After all, thats what debug information is there for.Karilla
Debug information is for the use of the debugger, not the program. If you need access to data by name in a C program, build a hash table.Thumbsdown
@LeeDanielCrocker There is no law that restricts using debug info to the debugger and prohibits a program from examining its own debug info. One use case is where the program prints its own crash stack trace with symbol, file and line info (often in a cluster environment, where getting a core dump is inconvenient).Kuwait

© 2022 - 2024 — McMap. All rights reserved.