免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1650 | 回复: 0
打印 上一主题 下一主题

ltrace的源代码分析以及修改。 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-04-02 13:47 |只看该作者 |倒序浏览

ltrace其可以打印出程序运行过程中的库函数调用,其原理是通过解析elf文件,找到需要解析的符号,及该符号所对应的地址。在程序运行起来后,首先使用ptrace技术,将该符号对应的位置替换为软件中断,这样在程序运行到该中断时,会通知ltrace,ltrace从而能打印出当时所调用的函数。

在ltrace中,只时能够列出库函数的调用,那么如何来列出自身的函数调用呢?
在elf文件中,我们可以找到symbol的section,该section中包含了程序中所用到的所有符号。
其格式如下
  typedef struct {
      Elf32_Word st_name;
      Elf32_Addr st_value;
      Elf32_Word st_size;
      unsigned char st_info;
      unsigned char st_other;
      Elf32_Half st_shndx;
  } Elf32_Sym;

st_name为symbol section所连接的string section的偏移量。

* st_value
  This member gives the value of the associated symbol. Depending on
  the context, this may be an absolute value, an address, etc.;
  details appear below.

* st_info
  This member specifies the symbol's type and binding attributes.  A
  list of the values and meanings appears below. The following code
  shows how to manipulate the values.
    #define ELF32_ST_BIND(i) ((i)>>4)
    #define ELF32_ST_TYPE(i) ((i)&0xf)
    #define ELF32_ST_INFO(b, t) (((b)

+ Figure 1-18: Symbol Types, ELF32_ST_TYPE
  Name         Value
  ====         =====
  STT_NOTYPE       0
  STT_OBJECT       1
  STT_FUNC         2
  STT_SECTION      3
  STT_FILE         4
  STT_LOPROC      13
  STT_HIPROC      15

所以我们找到symbol表中,type为STT_FUNC,其st_value就是该函数所对应的起始位置。

在这里我们只要修改ltrace中的elf.c文件中的do_init_elf (struct ltelf *lte, const char *filename);
增加如下部分,来读取SYMTAB表。
else if (shdr.sh_type == SHT_SYMTAB)
{
   Elf_Data *data;
   size_t j;
   lte->symbol = elf_getdata (scn, NULL);
   if (lte->symbol == NULL || elf_getdata (scn, lte->symbol) != NULL)
     error (EXIT_FAILURE, 0, "Couldn't get .symbol data from \"%s\"",
     filename);
      
      lte->symbol_count=shdr.sh_size/shdr.sh_entsize;

     scn = elf_getscn (lte->elf, shdr.sh_link);
     if (scn == NULL || gelf_getshdr (scn, &shdr) == NULL)
       error (EXIT_FAILURE, 0, "Couldn't get section header from \"%s\"",
         filename);
    data = elf_getdata (scn, NULL);
     if (data == NULL || elf_getdata (scn, data) != NULL
       || shdr.sh_size != data->d_size || data->d_off)
     error (EXIT_FAILURE, 0, "Couldn't get .symbolstr data from \"%s\"",
     filename);
    lte->symbolstr = data->d_buf;
    }

修改read_elf (const char *filename)
  for (i = 0; i symbol_count; ++i)   //读取每个符号
  {
     GElf_Sym sym;
     const char *name;
     GElf_Addr addr;
     if(gelf_getsym(lte->symbol,i,&sym) == NULL)   
         error (EXIT_FAILURE, 0, "Couldn't get symbol data from \"%s\"",filename);
     if (ELF32_ST_TYPE(sym.st_info) != STT_FUNC)  //找出符号类型为STT_FUNC
         continue;     
     
     name=lte->symbolstr+sym.st_name;        //将符号名称从偏移量转换为具体的值。
     if (in_load_libraries (name, lte))
     {
        addr = sym.st_value;
        if (addr != 0)
           add_library_symbol (addr, name, &library_symbols);  //将符号加入到全局的hash表中。
     }
  }

其他代码就不用修改了,可见ltrace代码的结构性与层次性非常的清晰。



本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/30686/showart_269561.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP