remove warnings
[dyninst.git] / dyninstAPI / src / Object-elf.h
1 /************************************************************************
2  * Object-elf32.h: ELF-32 object files.
3 ************************************************************************/
4
5
6 \f
7
8
9 #if !defined(_Object_elf32_h_)
10 #define _Object_elf32_h_
11
12
13 \f
14
15
16 /************************************************************************
17  * header files.
18 ************************************************************************/
19
20 #include <util/h/Dictionary.h>
21 #include <util/h/Line.h>
22 #include <util/h/String.h>
23 #include <util/h/Symbol.h>
24 #include <util/h/Types.h>
25 #include <util/h/Vector.h>
26
27 extern "C" {
28 #include <libelf.h>
29 #include <fcntl.h>
30 #include <stdlib.h>
31 #include <unistd.h>
32
33 #include <sys/types.h>
34 #include <sys/mman.h>
35 #include <sys/stat.h>
36 }
37
38
39 \f
40
41
42 /************************************************************************
43  * class Object
44 ************************************************************************/
45
46 class Object : public AObject {
47 public:
48              Object (const string, void (*)(const char *) = log_msg);
49              Object (const Object &);
50     virtual ~Object ();
51
52     const Object& operator= (const Object &);
53
54 private:
55     static
56     void    log_elferror (void (*)(const char *), const char *);
57
58     bool      loaded_elf (int, bool &, Elf* &, Elf32_Ehdr* &, Elf32_Phdr* &,
59                           unsigned &, unsigned &, Elf_Scn* &, Elf_Scn* &);
60     void     load_object ();
61 };
62
63 inline
64 Object::Object(const string file, void (*err_func)(const char *))
65     : AObject(file, err_func) {
66     load_object();
67 }
68
69 inline
70 Object::Object(const Object& obj)
71     : AObject(obj) {
72     load_object();
73 }
74
75 inline
76 Object::~Object() {
77 }
78
79 inline
80 const Object&
81 Object::operator=(const Object& obj) {
82     (void) AObject::operator=(obj);
83     return *this;
84 }
85
86 inline
87 void
88 Object::log_elferror(void (*pfunc)(const char *), const char* msg) {
89     const char* err = elf_errmsg(elf_errno());
90     log_printf(pfunc, "%s: %s\n", msg, err ? err : "(bad elf error)");
91 }
92
93 inline
94 bool
95 Object::loaded_elf(int fd, bool& did_elf, Elf*& elfp, Elf32_Ehdr*& ehdrp,
96     Elf32_Phdr*& phdrp, unsigned& txtaddr, unsigned& bssaddr,
97     Elf_Scn*& symscnp, Elf_Scn*& strscnp) {
98
99     elf_version(EV_CURRENT);
100     elf_errno();
101
102     if (((elfp = elf_begin(fd, ELF_C_READ, 0)) == 0)
103         || (elf_kind(elfp) != ELF_K_ELF)) {
104         log_elferror(err_func_, "opening file");
105         return false;
106     }
107     did_elf = true;
108
109     if (((ehdrp = elf32_getehdr(elfp)) == 0)
110         || (ehdrp->e_ident[EI_CLASS] != ELFCLASS32)
111         || (ehdrp->e_type != ET_EXEC)
112         || (ehdrp->e_phoff == 0)
113         || (ehdrp->e_shoff == 0)
114         || (ehdrp->e_phnum == 0)
115         || (ehdrp->e_shnum == 0)) {
116         log_elferror(err_func_, "loading eheader");
117         return false;
118     }
119
120     if ((phdrp = elf32_getphdr(elfp)) == 0) {
121         log_elferror(err_func_, "loading pheader");
122         return false;
123     }
124
125     Elf_Scn*    shstrscnp  = 0;
126     Elf32_Shdr* shstrshdrp = 0;
127     Elf_Data*   shstrdatap = 0;
128     if (((shstrscnp = elf_getscn(elfp, ehdrp->e_shstrndx)) == 0)
129         || ((shstrshdrp = elf32_getshdr(shstrscnp)) == 0)
130         || ((shstrdatap = elf_getdata(shstrscnp, 0)) == 0)) {
131         log_elferror(err_func_, "loading header section");
132         return false;
133     }
134
135     const char* shnames = (const char *) shstrdatap->d_buf;
136     Elf_Scn*    scnp    = 0;
137     while ((scnp = elf_nextscn(elfp, scnp)) != 0) {
138         Elf32_Shdr* shdrp = elf32_getshdr(scnp);
139         if (!shdrp) {
140             log_elferror(err_func_, "scanning sections");
141             return false;
142         }
143
144         const char* TEXT_NAME   = ".text";
145         const char* BSS_NAME    = ".bss";
146         const char* SYMTAB_NAME = ".symtab";
147         const char* STRTAB_NAME = ".strtab";
148         const char* name        = (const char *) &shnames[shdrp->sh_name];
149         if (strcmp(name, TEXT_NAME) == 0) {
150             txtaddr = shdrp->sh_addr;
151         }
152         else if (strcmp(name, BSS_NAME) == 0) {
153             bssaddr = shdrp->sh_addr;
154         }
155         else if (strcmp(name, SYMTAB_NAME) == 0) {
156             symscnp = scnp;
157         }
158         else if (strcmp(name, STRTAB_NAME) == 0) {
159             strscnp = scnp;
160         }
161     }
162     if (!txtaddr || !bssaddr || !symscnp || !strscnp) {
163         log_elferror(err_func_, "no text/bss/symbol/string section");
164         return false;
165     }
166
167     return true;
168 }
169
170 inline
171 void
172 Object::load_object() {
173     const char* file = file_.string_of();
174     struct stat st;
175     int         fd   = -1;
176     char*       ptr  = 0;
177     Elf*        elfp = 0;
178
179     bool        did_open = false;
180     bool        did_elf  = false;
181
182     /* try */ {
183         if (((fd = open(file, O_RDONLY)) == -1) || (fstat(fd, &st) == -1)) {
184             log_perror(err_func_, file);
185             /* throw exception */ goto cleanup;
186         }
187         did_open = true;
188
189         if ((ptr = (char *) mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0))
190             == (char *) -1) {
191             log_perror(err_func_, "mmap");
192             /* throw exception */ goto cleanup;
193         }
194
195         Elf32_Ehdr* ehdrp   = 0;
196         Elf32_Phdr* phdrp   = 0;
197         Elf_Scn*    symscnp = 0;
198         Elf_Scn*    strscnp = 0;
199         unsigned    txtaddr = 0;
200         unsigned    bssaddr = 0;
201         if (!loaded_elf(fd, did_elf, elfp, ehdrp, phdrp, txtaddr,
202             bssaddr, symscnp, strscnp)) {
203             /* throw exception */ goto cleanup;
204         }
205
206         for (unsigned i = 0; i < ehdrp->e_phnum; i++) {
207             if ((phdrp[i].p_vaddr <= txtaddr)
208                 && ((phdrp[i].p_vaddr+phdrp[i].p_memsz) >= txtaddr)) {
209                 code_ptr_ = (Word *) ((void*)&ptr[phdrp[i].p_offset]);
210                 code_off_ = (Address) phdrp[i].p_vaddr;
211                 code_len_ = (unsigned) phdrp[i].p_memsz / sizeof(Word);
212             }
213             else if ((phdrp[i].p_vaddr <= bssaddr)
214                 && ((phdrp[i].p_vaddr+phdrp[i].p_memsz) >= bssaddr)) {
215                 data_ptr_ = (Word *) ((void *) &ptr[phdrp[i].p_offset]);
216                 data_off_ = (Address) phdrp[i].p_vaddr;
217                 data_len_ = (unsigned) phdrp[i].p_memsz / sizeof(Word);
218             }
219         }
220         if (!code_ptr_ || !code_off_ || !code_len_) {
221             log_printf(err_func_, "cannot locate instructions\n");
222             /* throw exception */ goto cleanup;
223         }
224         if (!data_ptr_ || !data_off_ || !data_len_) {
225             log_printf(err_func_, "cannot locate data segment\n");
226             /* throw exception */ goto cleanup;
227         }
228
229         Elf_Data* symdatap = elf_getdata(symscnp, 0);
230         Elf_Data* strdatap = elf_getdata(strscnp, 0);
231         if (!symdatap || !strdatap) {
232             log_elferror(err_func_, "locating symbol/string data");
233             /* throw exception */ goto cleanup;
234         }
235
236         Elf32_Sym*  syms   = (Elf32_Sym *) symdatap->d_buf;
237         unsigned    nsyms  = symdatap->d_size / sizeof(Elf32_Sym);
238         const char* strs   = (const char *) strdatap->d_buf;
239         string      module = "DEFAULT_MODULE";
240         string      name   = "DEFAULT_NAME";
241         for (i = 0; i < nsyms; i++) {
242             Symbol::SymbolLinkage linkage =
243                 ((ELF32_ST_BIND(syms[i].st_info) == STB_LOCAL)
244                 ? Symbol::SL_LOCAL
245                 : Symbol::SL_GLOBAL);
246
247             bool st_kludge = false;
248             Symbol::SymbolType type = Symbol::ST_UNKNOWN;
249             switch (ELF32_ST_TYPE(syms[i].st_info)) {
250             case STT_FILE:
251                 module = string(&strs[syms[i].st_name]);
252                 type   = Symbol::ST_MODULE;
253                 break;
254
255             case STT_OBJECT:
256                 type = Symbol::ST_OBJECT;
257                 break;
258
259             case STT_FUNC:
260                 type = Symbol::ST_FUNCTION;
261                 break;
262
263             default:
264                 continue;
265             }
266
267             name = string(&strs[syms[i].st_name]);
268             symbols_[name] = Symbol(name, module, type, linkage,
269                                     syms[i].st_value, st_kludge);
270         }
271     }
272
273     /* catch */
274 cleanup: {
275         if (did_elf && (elf_end(elfp) != 0)) {
276             log_elferror(err_func_, "closing file");
277         }
278         if (did_open && (close(fd) == -1)) {
279             log_perror(err_func_, "close");
280         }
281     }
282 }
283
284
285 \f
286
287
288 #endif /* !defined(_Object_elf32_h_) */