dladdr(3)
π dladdr, dladdr1 π
okay so this is dladdr(3) from the Library Functions Manual and bestie, if you've ever stared at a raw pointer like "who even ARE you" β this is the page for you. πΈ
β¨ NAME β¨
dladdr, dladdr1 β translate address to symbolic information
π LIBRARY π
Dynamic linking library (libdl, -ldl) π¦
π SYNOPSIS π
#define _GNU_SOURCE
#include <dlfcn.h>
int dladdr(const void *addr, Dl_info *info);
int dladdr1(const void *addr, Dl_info *info, void **extra_info,
int flags);
π DESCRIPTION π
So dladdr() is literally the function that answers "hey, whose address is this??" π΅οΈβοΈ You hand it an address in addr, and it checks whether that address lives inside one of the shared objects your program has loaded. If it does, you get back info about the shared object and the symbol that overlaps addr. All of that lands in a Dl_info structure, and it looks like this:
typedef struct {
const char *dli_fname; /* Pathname of shared object that
contains address */
void *dli_fbase; /* Base 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;
And if literally no symbol matches addr? Then dli_sname and dli_saddr get set to NULL. No symbol, no name, periodt. π
Now dladdr1() is giving "same energy, but extra." It's like dladdr(), except it also hands you more info through the extra_info argument. What you actually get back depends on what you put in flags, and flags can be one of these:
RTLD_DL_LINKMAPβ bestie you get a pointer to the link map for the matched file. Theextra_infoargument points to a pointer to alink_mapstructure (so like,struct link_map **), and that structure is defined in<link.h>like this:
struct link_map {
ElfW(Addr) l_addr; /* Difference between the
address in the ELF file and
the address in memory */
char *l_name; /* Absolute pathname where
object was found */
ElfW(Dyn) *l_ld; /* Dynamic section of the
shared object */
struct link_map *l_next, *l_prev;
/* Chain of loaded objects */
/* Plus additional fields private to the
implementation */
};
RTLD_DL_SYMENTβ now you get a pointer to the ELF symbol table entry of the matching symbol. Theextra_infoargument here is a pointer to a symbol pointer:const ElfW(Sym) **. And theElfW()macro? It turns its argument into the name of an ELF data type that's suitable for your hardware architecture. So on a 64-bit platform,ElfW(Sym)gives you the data type nameElf64_Sym, which is defined in<elf.h>like so:
typedef struct {
Elf64_Word st_name; /* Symbol name */
unsigned char st_info; /* Symbol type and binding */
unsigned char st_other; /* Symbol visibility */
Elf64_Section st_shndx; /* Section index */
Elf64_Addr st_value; /* Symbol value */
Elf64_Xword st_size; /* Symbol size */
} Elf64_Sym;
The st_name field is an index into the string table. π§΅
The st_info field encodes the symbol's type and binding. You pull the type out with the macro ELF64_ST_TYPE(st_info) (or ELF32_ST_TYPE() on 32-bit platforms), and it yields one of these:
STT_NOTYPEβ Symbol type is unspecifiedSTT_OBJECTβ Symbol is a data objectSTT_FUNCβ Symbol is a code objectSTT_SECTIONβ Symbol associated with a sectionSTT_FILEβ Symbol's name is filenameSTT_COMMONβ Symbol is a common data objectSTT_TLSβ Symbol is thread-local data objectSTT_GNU_IFUNCβ Symbol is indirect code object
The symbol binding comes out of that same st_info field using the macro ELF64_ST_BIND(st_info) (or ELF32_ST_BIND() on 32-bit platforms), and it yields one of these:
STB_LOCALβ Local symbolSTB_GLOBALβ Global symbolSTB_WEAKβ Weak symbolSTB_GNU_UNIQUEβ Unique symbol
And the st_other field holds the symbol's visibility, which you extract with the macro ELF64_ST_VISIBILITY(st_info) (or ELF32_ST_VISIBILITY() on 32-bit platforms), and it yields one of these:
STV_DEFAULTβ Default symbol visibility rulesSTV_INTERNALβ Processor-specific hidden classSTV_HIDDENβ Symbol unavailable in other modulesSTV_PROTECTEDβ Not preemptible, not exported
π RETURN VALUE π
On success, these functions return a nonzero value. π« But listen: if the address in addr matched a shared object but not a symbol inside that shared object, then info->dli_sname and info->dli_saddr get set to NULL. Symbol found: no. Shared object found: yes.
If the address in addr couldn't be matched to a shared object at all, then these functions return 0. And in that case? An error message is not available via dlerror(3). So don't go asking dlerror(3) for the tea, it has none. π
β ATTRIBUTES β
For an explanation of the terms used in this section, see attributes(7).
- Interface:
dladdr(),dladdr1() - Attribute: Thread safety
- Value: MT-Safe
(Yeah bestie, MT-Safe, we love a thread-safe icon. π)
π¦ STANDARDS π¦
GNU.
π°οΈ HISTORY π°οΈ
dladdr()β glibc 2.0.dladdr1()β glibc 2.3.3.- Solaris.
π BUGS π
ngl, sometimes the function pointers you pass to dladdr() will surprise you. π On some architectures (notably i386 and x86-64), dli_fname and dli_fbase may end up pointing back at the object you called dladdr() from β even if the function used as an argument is supposed to come from a dynamically linked library. Like, betrayal.
The problem is that the function pointer is still resolved at compile time, but it merely points to the plt (Procedure Linkage Table) section of the original object β and that section is the one that dispatches the call after asking the dynamic linker to resolve the symbol. So yeah. Main character pointer, wrong address. β¨
To work around this, you can try compiling the code to be position-independent: then the compiler can't prepare the pointer at compile time anymore, andgcc(1)generates code that just loads the final symbol address from the got (Global Offset Table) at run time before passing it todladdr(). Slay. π«Ά
π SEE ALSO π
dl_iterate_phdr(3), dlinfo(3), dlopen(3), dlsym(3), ld.so(8)
and that's the whole page, bestie β this was Linux man-pages 6.20, dated 2026-02-08, for dladdr(3) π go forth and translate those addresses, you absolute legend πβ¨
π¦ where this page comes from
- arch rolling: man-pages 6.20-1 Β· BSD-2-Clause AND BSD-3-Clause AND BSD-4.3TAHOE AND BSD-4-Clause-UC AND GPL-1.0-or-later AND GPL-2.0-only AND GPL-2.0-or-later AND GPL-3.0-or-later AND LGPL-3.0-linking-exception AND LGPL-3.0-or-later AND LicenseRef-Public-Domain AND LicenseRef-UltraPermissive AND Linux-man-pages-1-para AND Linux-man-pages-copyleft AND Linux-man-pages-copyleft-2-para AND Linux-man-pages-copyleft-var AND MIT AND Spencer-94
- nixpkgs unstable: man-pages 6.20
- π the page's license: Linux-man-pages-copyleft
- Copyright 2008, Petr Baudis <pasky@ucw.cz>
- Copyright 2015, Michael Kerrisk <mtk.manpages@gmail.com>
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms