免费注册 查看新帖 |

Chinaunix

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

解析elf文件 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-03-28 11:37 |只看该作者 |倒序浏览
阅读了ltrace的代码,才发现了关于elf的开发包,这对于我们将来分析程序很有帮助。

学习该开发包时,我推荐的学习方法:
readelf -a  

了解elf文件的格式,可以参考
http://blog.chinaunix.net/u/30686/showart_250105.html

另外下面列出一篇文章,大家可以参考,接下来我将分析ltrace的代码,来学习关于elf的开发包用法。

LibElf and GElf - A Library to Manipulate ELf Files

By Neelakanth Nadgir, August 2001   


This article provides a short introduction to using the ELF manipulation library, which is provided as a part of the Solaris operating environment. Programmers with little to medium experience and an interest in knowing about object/library file format will find it useful.
Introduction
Executable and Linkable Format is a portable object file format supported by most UNIX® vendors. It is the dominant file format for UNIX executables, object files and libraries. ELF was originally developed and published by UNIX System Laboratories, and defines the format of an ELF object file.
ELF helps developers by providing a set of binary interface definitions that are cross-platform, and by making it easier for tool vendors to port to multiple platforms. Having a standard object file format also makes porting of object-manipulating programs easier. Compilers, debuggers, and linkers are some examples of tools that use the ELF format.
ELF
The ELF specification describes three kinds of object files.
Relocatable files - Hold code and data suitable for linking with other object files
Executable files - Hold code and data that can be executed on the target operating system
Shared object files - Hold relocatable data that can be statically and dynamically shared with other shared objects
Relocatable files are also called as object files (.o files). They are generated by the compiler during compilation of a source file (such as a C or C++ file). These object files are then processed by the linker to produce either an ELF executable or shared objects (also called shared libraries). Executable ELF objects can then be executed by the user. A shared library is a collection of routines that different object files or executables can share. Shared libraries are made up of several object files with position independent code (PIC).
Source file (.cpp, .c, .f) -----> Object files (.o) -----> Elf Executable
|-------> Shared Object (.so)
ASCII file format ELF file format
[pastwatch] c > cat sample.c
#include
main()
{
printf("Hello Worldn");
}
[pastwatch] c > cc -c sample.c
[pastwatch] c > cc -o sample sample.o
[pastwatch] c >file sample.c sample.o sample
sample.c:   c program text
sample.o:   ELF 32-bit MSB relocatable SPARC Version 1
sample:     ELF 32-bit MSB executable SPARC
              Version 1, dynamically linked, not stripped
Every ELF file has an ELF header and a number of sections. An ELF header is present for all ELF objects. This means that the presence of the ELF header identifies the file to be an ELF file. If the ELF object is executable, it has a Program Header Table following the ELF header. ELF objects that are not executable (that is .o object files) have a Section Header Table at the end of the file. The format of the ELF header and sections is part of the ELF specification, and is defined in /usr/include/sys/elf.h .
Table 1 describes the ELF file format. The first column is the field and the second column is the format of that field.
Table 1 Object File Format
Field Format of the field
ELF header typedef struct {
unsigned char e_ident[EI_NIDENT];    /* ident bytes */
Elf32_Half e_type;                   /* file type */
Elf32_Half e_machine;                /* target machine */
Elf32_Word e_version;                /* file version */
Elf32_Addr e_entry;                  /* start address */
Elf32_Off e_phoff;                   /* phdr file offset */
Elf32_Off e_shoff;                   /* shdr file offset */
Elf32_Word e_flags;                  /* file flags */
Elf32_Half e_ehsize;                 /* sizeof ehdr */
Elf32_Half e_phentsize;              /* sizeof phdr */
Elf32_Half e_phnum;                  /* number phdrs */
Elf32_Half e_shentsize;              /* sizeof shdr */
Elf32_Half e_shnum;                  /* number shdrs */
Elf32_Half e_shstrndx;               /* shdr string index */
} Elf32_Ehdr;

Program header table (optional) typedef struct {
   Elf32_Word p_type;  /* entry type */
   Elf32_Off p_offset;  /* file offset */
   Elf32_Addr p_vaddr;  /* virtual address */
   Elf32_Addr p_paddr;  /* physical address */
   Elf32_Word p_filesz; /* file size */
   Elf32_Word p_memsz;  /* memory size */
   Elf32_Word p_flags;  /* entry flags */
   Elf32_Word p_align;  /* memory/file alignment */
} Elf32_Phdr;

Section 1 Each section contains a section header followed by chunks of data. These chunks of data are dependent on the type of the section. For example, if the section is of type SHT_SYMTAB, the section contains an array of symbols. The type of the section dictates the structures contained in the section. The section header is the same for all sections, and is of the type:
typedef struct {
   Elf32_Word sh_name;   /* section name */
   Elf32_Word sh_type;   /* SHT_... */
   Elf32_Word sh_flags;  /* SHF_... */
   Elf32_Addr sh_addr;   /* virtual address */
   Elf32_Off sh_offset;  /* file offset */
   Elf32_Word sh_size;   /* section size */
   Elf32_Word sh_link;   /* misc info */
   Elf32_Word sh_info;   /* misc info */
   Elf32_Word sh_addralign;  /* memory alignment */
   Elf32_Word sh_entsize;  /* entry size if table */
} Elf32_Shdr;

... ...  
Section n Contains the section header and data  
... ...  
Section header table ...  

LibElf and GElf
The Solaris operating environment provides an object file access library, libelf(3LIB), that can be used to manipulate object files, archive files, and archive members. The generic version of this library, which handles both 32 bit and 64 bit objects, is called GElf. Several demo programs are also provided as a part of the SUNWosdem package, and can be found in /usr/demo/ELF.
The Solaris man page for GElf(3ELF) (man gelf ) states that:
GElf is a generic, ELF class independent API, for manipulating ELF object files. GElf provides a single, common interface for handling 32-bit and 64-bit ELF format object files. GElf is a translation layer between the application and the class dependent parts of the ELF library. Thus, the application can use GElf, which in turn, will call the corresponding elf32_ or elf64_ functions on behalf of the application.
Programs that need to use LibElf to manipulate an ELF file should do the following:
Check that there are no version inconsistencies.
if (elf_version(EV_CURRENT) == EV_NONE ) {
/* library out of date */
fprintf(stderr, "Elf library out of date!n");
exit(-1);
}
Open the file using the open() system call. For example, if the name of the file is in argv[1], the following code can be used to open the file.
fd = open(argv[1], O_RDONLY);
Indicate to LibElf that this file is to be associated with an ELF object. This is achieved by calling the elf_begin function. elf_begin returns an ELF descriptor (of type Elf* ) that is then used to call other functions in the library.
if ((elf = elf_begin(fd, ELF_C_READ, NULL)) == NULL){
         /*error*/
}  
Programs get the ELF descriptor, and then read the ELF header. You can then read sections and manipulate them.
Examples
Here are some simple code fragments that demonstrate how to use LibElf to manipulate object files.
Example 1 - Check if the symbol table exists.
/* Check if Symbol Table exists */
bool check_symbol_table()
{
     Elf_Scn* section = 0;
     int number = 0;
     while ((section = elf_nextscn(elf, scn)) != 0) {
        char *name = 0;
        Elf32_Shdr *shdr;
        if ((shdr = elf32_getshdr (section)) != 0) {
                if (shdr->sh_type == SHT_SYMTAB) {
                    /* Change SHT_SYMTAB to SHT_DYNSYM
                     * to access the dynamic symbol table
                     */
                     printf("Found Symbol Tablen");
                     /* You can use the function given below to pri nt
                      * out the symbol table
                      * print_symbols(elf, section, shdr);
                      */
                      return TRUE;
                  }
         }
     }
     /* no symtab */
     return FALSE;
}
Example 2 - Print the symbol table.
/* Given Elf header, Elf_Scn, and Elf32_Shdr
* print out the symbol table
*/
print_symbols(Elf *elf, Elf_Scn *scn, Elf32_Shdr *shdr)
{
      Elf_Data *data;
      char *name;
      char *stringName;
      data = 0;
      int number = 0;
      if ((data = elf_getdata(scn, data)) == 0 || data->d_size == 0){
          /* error or no data */
          fprintf(stderr,"Section had no data!n");
               exit(-1);
      }
      /*now print the symbols*/
      Elf32_Sym *esym = (Elf32_Sym*) data->d_buf;
      Elf32_Sym *lastsym = (Elf32_Sym*) ((char*) data->d_buf + data->d_size);
      /* now loop through the symbol table and print it*/
      for (; esym st_value == 0) ||
                (ELF32_ST_BIND(esym->st_info)== STB_WEAK) ||
                (ELF32_ST_BIND(esym->st_info)== STB_NUM) ||
                (ELF32_ST_TYPE(esym->st_info)!= STT_FUNC))
                    continue;
           name = elf_strptr(elf,shdr->sh_link , (size_t)esym->st_name);
           if(!name){
                fprintf(stderr,"%sn",elf_errmsg(elf_errno()));
                exit(-1);
           }
           printf("%d: %sn",number++, name);
       }
}
Example 3 - Finding a file type.
This example uses the GElf interface to manipulate both 32-bit and 64-bit ELF objects. Using GElf is very similar to using the LibElf interface, as demonstrated below. (You can download the entire source code.)
static void my_error(const char *fmt, ...);
static void print_usage(char *exename)
{
  fprintf(stderr,"Usage: %s filen", exename);
}
int main(int argc, char *argv[])
{
  int fd;
  int filetype;
  Elf *elf;
  GElf_Ehdr elfhdr;
  char *type, *machine, *kind, *class;
  if(argc != 2){
    print_usage(argv[0]);
    exit(-1);
  }
  if (elf_version(EV_CURRENT) == EV_NONE) {
    /* library out of date */
    my_error("ELF library is out of date, Quittingn");
  }
  fd = open(argv[1],O_RDONLY);
  if (fd  ./filetype filetype
filetype: ELF 64-bit executable SPARCV9
[pastwatch] elf > ./filetype /usr/lib/libc.so
/usr/lib/libc.so: ELF 32-bit dynamic lib SPARC
[pastwatch] elf > ./filetype /usr/lib/sparcv9/libc.so
/usr/lib/sparcv9/libc.so: ELF 64-bit dynamic lib SPARCV9
[pastwatch] elf > ./filetype /bin/ls
/bin/ls: ELF 32-bit executable SPARC
[pastwatch] elf > ./filetype ./filetype.o
./filetype.o: ELF 32-bit relocatable SPARC
*********************************************/
Resources
The Solaris man pages for LibElf and GElf are very descriptive and provide useful examples.
About the Author
Neelakanth Nadgir is a software engineer in Sun's Market Development Engineering organization. He works with tool vendors to develop "best of breed" applications on Sun systems. He also volunteers for the GNU project. In his spare time, he likes to go hiking in Big Basin State Park.
August 2001



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

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP