agent/src/os/linux/salibelf.c

Sat, 01 Dec 2007 00:00:00 +0000

author
duke
date
Sat, 01 Dec 2007 00:00:00 +0000
changeset 435
a61af66fc99e
child 1907
c18cbe5936b8
permissions
-rw-r--r--

Initial load

     1 /*
     2  * Copyright 2003-2006 Sun Microsystems, Inc.  All Rights Reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.
     8  *
     9  * This code is distributed in the hope that it will be useful, but WITHOUT
    10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    12  * version 2 for more details (a copy is included in the LICENSE file that
    13  * accompanied this code).
    14  *
    15  * You should have received a copy of the GNU General Public License version
    16  * 2 along with this work; if not, write to the Free Software Foundation,
    17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    18  *
    19  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
    20  * CA 95054 USA or visit www.sun.com if you need additional information or
    21  * have any questions.
    22  *
    23  */
    25 #include "salibelf.h"
    26 #include <stdlib.h>
    27 #include <unistd.h>
    29 extern void print_debug(const char*,...);
    31 // ELF file parsing helpers. Note that we do *not* use libelf here.
    32 int read_elf_header(int fd, ELF_EHDR* ehdr) {
    33    if (pread(fd, ehdr, sizeof (ELF_EHDR), 0) != sizeof (ELF_EHDR) ||
    34             memcmp(&ehdr->e_ident[EI_MAG0], ELFMAG, SELFMAG) != 0 ||
    35             ehdr->e_version != EV_CURRENT) {
    36         return 0;
    37    }
    38    return 1;
    39 }
    41 bool is_elf_file(int fd) {
    42    ELF_EHDR ehdr;
    43    return read_elf_header(fd, &ehdr);
    44 }
    46 // read program header table of an ELF file
    47 ELF_PHDR* read_program_header_table(int fd, ELF_EHDR* hdr) {
    48    ELF_PHDR* phbuf = 0;
    49    // allocate memory for program header table
    50    size_t nbytes = hdr->e_phnum * hdr->e_phentsize;
    52    if ((phbuf = (ELF_PHDR*) malloc(nbytes)) == NULL) {
    53       print_debug("can't allocate memory for reading program header table\n");
    54       return NULL;
    55    }
    57    if (pread(fd, phbuf, nbytes, hdr->e_phoff) != nbytes) {
    58       print_debug("ELF file is truncated! can't read program header table\n");
    59       free(phbuf);
    60       return NULL;
    61    }
    63    return phbuf;
    64 }
    66 // read section header table of an ELF file
    67 ELF_SHDR* read_section_header_table(int fd, ELF_EHDR* hdr) {
    68    ELF_SHDR* shbuf = 0;
    69    // allocate memory for section header table
    70    size_t nbytes = hdr->e_shnum * hdr->e_shentsize;
    72    if ((shbuf = (ELF_SHDR*) malloc(nbytes)) == NULL) {
    73       print_debug("can't allocate memory for reading section header table\n");
    74       return NULL;
    75    }
    77    if (pread(fd, shbuf, nbytes, hdr->e_shoff) != nbytes) {
    78       print_debug("ELF file is truncated! can't read section header table\n");
    79       free(shbuf);
    80       return NULL;
    81    }
    83    return shbuf;
    84 }
    86 // read a particular section's data
    87 void* read_section_data(int fd, ELF_EHDR* ehdr, ELF_SHDR* shdr) {
    88   void *buf = NULL;
    89   if (shdr->sh_type == SHT_NOBITS || shdr->sh_size == 0) {
    90      return buf;
    91   }
    92   if ((buf = calloc(shdr->sh_size, 1)) == NULL) {
    93      print_debug("can't allocate memory for reading section data\n");
    94      return NULL;
    95   }
    96   if (pread(fd, buf, shdr->sh_size, shdr->sh_offset) != shdr->sh_size) {
    97      free(buf);
    98      print_debug("section data read failed\n");
    99      return NULL;
   100   }
   101   return buf;
   102 }
   104 uintptr_t find_base_address(int fd, ELF_EHDR* ehdr) {
   105   uintptr_t baseaddr = (uintptr_t)-1;
   106   int cnt;
   107   ELF_PHDR *phbuf, *phdr;
   109   // read program header table
   110   if ((phbuf = read_program_header_table(fd, ehdr)) == NULL) {
   111     goto quit;
   112   }
   114   // the base address of a shared object is the lowest vaddr of
   115   // its loadable segments (PT_LOAD)
   116   for (phdr = phbuf, cnt = 0; cnt < ehdr->e_phnum; cnt++, phdr++) {
   117     if (phdr->p_type == PT_LOAD && phdr->p_vaddr < baseaddr) {
   118       baseaddr = phdr->p_vaddr;
   119     }
   120   }
   122 quit:
   123   if (phbuf) free(phbuf);
   124   return baseaddr;
   125 }

mercurial