如何在C语言中查看Linux内存映射信息?

3

我正在使用C语言动态加载一些Linux库。使用

dlinfo

(参见1),我可以获取库的起始地址。

然而,我找不到任何获取库大小的信息。

唯一找到的方法是读取

/proc/[pid]/maps

文件,并解析相关信息(参见2)。是否有更优雅的方法?


1
据我所知,解析maps是最简单的方法。您为什么认为它不够优雅? - osgx
1
与仅执行以下操作相比,必须处理字符串解析不太美观。struct link_map *map; dlinfo(hLibrary, RTLD_DI_LINKMAP, &map); void* base = map->l_addr; - user1036752
有一个 map->l_name,你可以根据库的路径进行 stat。或者你可以尝试深入挖掘 link_map 并找到已加载的 ELF 文件的段/节。 - osgx
2个回答

0

(此答案仅适用于LINUX/GLIBC)

根据http://s.eresi-project.org/inc/articles/elf-rtld.txt的说法,有link_map *map; map->l_map_start & map->l_map_end。

    /* 
        ** Start and finish of memory map for this object.  
    ** l_map_start need not be the same as l_addr.  
    */
    ElfW(Addr) l_map_start, l_map_end;

这有点不准确,就像这里所说的http://www.cygwin.com/ml/libc-hacker/2007-06/msg00014.html一样。 = 一些库在内存中不是连续的;链接的信件中有一些例子...例如,这是用于检测给定地址是否在lib的地址空间内的非常内部(对rtld而言)的函数,基于link_map并直接使用ELF段:

/* Return non-zero if ADDR lies within one of L's segments.  */
int
internal_function
_dl_addr_inside_object (struct link_map *l, const ElfW(Addr) addr)
{
  int n = l->l_phnum;
  const ElfW(Addr) reladdr = addr - l->l_addr;

  while (--n >= 0)
    if (l->l_phdr[n].p_type == PT_LOAD
    && reladdr - l->l_phdr[n].p_vaddr >= 0
    && reladdr - l->l_phdr[n].p_vaddr < l->l_phdr[n].p_memsz)
      return 1;
  return 0;
}

这个函数是另一种选择,它是查找已加载的ELF程序头或节头(在link_map中有一些相关信息的链接)。

最简单的方法是使用一些stat系统调用和map->l_name - 从磁盘读取文件大小(在检测到巨大的bss段时不太准确)。


0
解析/proc/self/maps(或者使用pmap命令)对我来说似乎仍然是最简单的事情。此外,还有dladdr函数(前提是你有一些地址可以开始)。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接