Stackdb
Stackdb is a stackable, multi-target and -level source debugger and memory forensics library.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
debug_elf.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2011, 2012, 2013 The University of Utah
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License as
6  * published by the Free Software Foundation; either version 2 of
7  * the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18 
19 #include <stdlib.h>
20 #include <unistd.h>
21 #include <sys/types.h>
22 #include <sys/stat.h>
23 #include <fcntl.h>
24 #include <errno.h>
25 #include <string.h>
26 #include <stdint.h>
27 #include <inttypes.h>
28 #include <assert.h>
29 #include <regex.h>
30 
31 #include "config.h"
32 #include "log.h"
33 #include "output.h"
34 #include "list.h"
35 #include "clfit.h"
36 #include "alist.h"
37 #include "dwdebug.h"
38 
39 #include <dwarf.h>
40 #include <gelf.h>
41 #include <elfutils/libebl.h>
42 #include <elfutils/libdw.h>
43 #include <elfutils/libdwfl.h>
44 
45 #include "memory-access.h"
46 
48  GElf_Ehdr ehdr;
49 
50  if (!gelf_getehdr(elf,&ehdr)) {
51  verror("gelf_getehdr: %s\n",elf_errmsg(elf_errno()));
52  return DEBUGFILE_TYPE_NONE;
53  }
54 
55  if (ehdr.e_type == ET_EXEC)
56  return DEBUGFILE_TYPE_MAIN;
57  else if (ehdr.e_type == ET_DYN)
58  return DEBUGFILE_TYPE_SHAREDLIB;
59  else if (ehdr.e_type == ET_REL)
60  return DEBUGFILE_TYPE_LIB;
61  else {
62  verror("unrecognized ELF type %d!\n",ehdr.e_type);
63  return DEBUGFILE_TYPE_NONE;
64  }
65 }
66 
67 int elf_get_base_addrs(Elf *elf,
68  ADDR *base_virt_addr_saveptr,
69  ADDR *base_phys_addr_saveptr) {
70  GElf_Ehdr ehdr_mem;
71  GElf_Ehdr *ehdr;
72  GElf_Phdr phdr_mem;
73  GElf_Phdr *phdr;
74  size_t i;
75  ADDR base_phys_addr = 0;
76  ADDR base_virt_addr = 0;
77 
78  /*
79  * Search through all the program headers; for those of type LOAD,
80  * find the minimum phys addr (and its corresponding virt addr);
81  * take these addrs to be used in calculating the phys_offset later
82  * for use in virt<->phys addr translation from debuginfo virt addrs
83  * to phys machine addrs.
84  */
85  ehdr = gelf_getehdr(elf,&ehdr_mem);
86  if (ehdr && ehdr->e_phnum > 0) {
87  base_phys_addr = ADDRMAX;
88  base_virt_addr = ADDRMAX;
89 
90  for (i = 0; i < ehdr->e_phnum; ++i) {
91  if (!(phdr = gelf_getphdr(elf,i,&phdr_mem))) {
92  vwarn("could not read program header %d\n",(int)i);
93  continue;
94  }
95 
96  if (phdr->p_type != PT_LOAD)
97  continue;
98 
99  if (phdr->p_vaddr < base_virt_addr) {
100  base_phys_addr = phdr->p_paddr;
101  base_virt_addr = phdr->p_vaddr;
102  }
103  }
104  }
105 
106  /* If we didn't find anything (weird), make sure to use 0 as our
107  * base; it's the best we can do, realistically.
108  */
109  if (base_phys_addr == ADDRMAX && base_virt_addr == ADDRMAX)
110  base_phys_addr = base_virt_addr = 0;
111 
112  if (base_phys_addr_saveptr)
113  *base_phys_addr_saveptr = base_phys_addr;
114  if (base_virt_addr_saveptr)
115  *base_virt_addr_saveptr = base_virt_addr;
116 
117  return 0;
118 }
119 
121  int *has_debuginfo_saveptr,
122  char **buildid_saveptr,
123  char **gnu_debuglinkfile_saveptr,
124  uint32_t *gnu_debuglinkfile_crc_saveptr) {
125  Elf_Scn *scn;
126  GElf_Shdr shdr_mem;
127  GElf_Shdr *shdr;
128  size_t shstrndx;
129  Elf_Data *edata;
130  int is64;
131  Elf32_Nhdr *nthdr32;
132  Elf64_Nhdr *nthdr64;
133  char *ndata,*nend;
134  char *name;
135 
136  int has_debuginfo = 0;
137  char *buildid = NULL;
138  char *debuglinkfile = NULL;
139  uint32_t debuglinkfilecrc = 0;
140 
141  if (elf_get_arch_info(elf,&is64,NULL)) {
142  verror("elf_get_arch_info failed\n");
143  return -1;
144  }
145  is64 = (is64 == 8) ? 1 : 0;
146 
147 #if _INT_ELFUTILS_VERSION >= 152
148  if (elf_getshdrstrndx(elf,&shstrndx) < 0) {
149 #else
150  if (elf_getshstrndx(elf,&shstrndx) < 0) {
151 #endif
152  verror("cannot get section header string table index\n");
153  return -1;
154  }
155 
156  scn = NULL;
157  while ((scn = elf_nextscn(elf,scn)) != NULL) {
158  shdr = gelf_getshdr(scn,&shdr_mem);
159 
160  if (shdr && shdr->sh_size > 0) {
161  name = elf_strptr(elf,shstrndx,shdr->sh_name);
162 
163  if (strcmp(name,".debug_info") == 0) {
165  "found %s section (%d)\n",name,shdr->sh_size);
166  has_debuginfo = 1;
167  continue;
168  }
169  else if (!buildid && shdr->sh_type == SHT_NOTE) {
171  "found %s note section (%d)\n",name,shdr->sh_size);
172  edata = elf_rawdata(scn,NULL);
173  if (!edata) {
174  vwarn("cannot get data for valid section '%s': %s",
175  name,elf_errmsg(-1));
176  continue;
177  }
178 
179  ndata = edata->d_buf;
180  nend = ndata + edata->d_size;
181  while (ndata < nend) {
182  if (is64) {
183  nthdr64 = (Elf64_Nhdr *)ndata;
184  /* skip past the header and the name string and its
185  * padding */
186  ndata += sizeof(Elf64_Nhdr);
187  vdebug(5,LA_DEBUG,LF_DFILE,"found note name '%s'\n",ndata);
188  ndata += nthdr64->n_namesz;
189  if (nthdr64->n_namesz % 4)
190  ndata += (4 - nthdr64->n_namesz % 4);
191  vdebug(5,LA_DEBUG,LF_DFILE,"found note desc '%s'\n",ndata);
192  /* dig out the build ID */
193  if (nthdr64->n_type == NT_GNU_BUILD_ID) {
194  buildid = strdup(ndata);
195  break;
196  }
197  /* skip past the descriptor and padding */
198  ndata += nthdr64->n_descsz;
199  if (nthdr64->n_namesz % 4)
200  ndata += (4 - nthdr64->n_namesz % 4);
201  }
202  else {
203  nthdr32 = (Elf32_Nhdr *)ndata;
204  /* skip past the header and the name string and its
205  * padding */
206  ndata += sizeof(Elf32_Nhdr);
207  ndata += nthdr32->n_namesz;
208  if (nthdr32->n_namesz % 4)
209  ndata += (4 - nthdr32->n_namesz % 4);
210  /* dig out the build ID */
211  if (nthdr32->n_type == NT_GNU_BUILD_ID) {
212  buildid = strdup(ndata);
213  break;
214  }
215  /* skip past the descriptor and padding */
216  ndata += nthdr32->n_descsz;
217  if (nthdr32->n_namesz % 4)
218  ndata += (4 - nthdr32->n_namesz % 4);
219  }
220  }
221  }
222  else if (strcmp(name,".gnu_debuglink") == 0) {
223  edata = elf_rawdata(scn,NULL);
224  if (!edata) {
225  vwarn("cannot get data for valid section '%s': %s",
226  name,elf_errmsg(-1));
227  continue;
228  }
229  debuglinkfile = strdup(edata->d_buf);
230  debuglinkfilecrc = *(uint32_t *)(edata->d_buf + edata->d_size - 4);
231  }
232  }
233  }
234 
235  if (has_debuginfo_saveptr)
236  *has_debuginfo_saveptr = has_debuginfo;
237  if (buildid_saveptr)
238  *buildid_saveptr = buildid;
239  else if (buildid)
240  free(buildid);
241  if (gnu_debuglinkfile_saveptr)
242  *gnu_debuglinkfile_saveptr = debuglinkfile;
243  else if (debuglinkfile)
244  free(debuglinkfile);
245  if (gnu_debuglinkfile_crc_saveptr)
246  *gnu_debuglinkfile_crc_saveptr = debuglinkfilecrc;
247 
248  return 0;
249 }
250 
251 int elf_get_arch_info(Elf *elf,int *wordsize,int *endian) {
252  char *eident;
253 
254  /* read the ident stuff to get wordsize and endianness info */
255  if (!(eident = elf_getident(elf,NULL))) {
256  verror("elf_getident: %s\n",elf_errmsg(elf_errno()));
257  return -1;
258  }
259 
260  if ((uint8_t)eident[EI_CLASS] == ELFCLASS32) {
261  if (wordsize)
262  *wordsize = 4;
263  vdebug(3,LA_DEBUG,LF_ELF,"32-bit\n");
264  }
265  else if ((uint8_t)eident[EI_CLASS] == ELFCLASS64) {
266  if (wordsize)
267  *wordsize = 8;
268  vdebug(3,LA_DEBUG,LF_ELF,"64-bit\n");
269  }
270  else {
271  verror("unknown elf class %d; not 32/64 bit!\n",
272  (uint8_t)eident[EI_CLASS]);
273  return -1;
274  }
275 
276  if ((uint8_t)eident[EI_DATA] == ELFDATA2LSB) {
277  if (endian)
278  *endian = DATA_LITTLE_ENDIAN;
279  vdebug(3,LA_DEBUG,LF_DFILE,"little endian\n");
280  }
281  else if ((uint8_t)eident[EI_DATA] == ELFDATA2MSB) {
282  if (endian)
283  *endian = DATA_BIG_ENDIAN;
284  vdebug(3,LA_DEBUG,LF_DFILE,"big endian\n");
285  }
286  else {
287  verror("unknown elf data %d; not big/little endian!\n",
288  (uint8_t)eident[EI_DATA]);
289  return -1;
290  }
291 
292  return 0;
293 }
294 
295 int elf_is_dynamic_exe(Elf *elf) {
296  Elf_Scn *scn;
297  GElf_Shdr shdr_mem;
298  GElf_Shdr *shdr;
299  char *name;
300  size_t shstrndx;
301 
302 #if _INT_ELFUTILS_VERSION >= 152
303  if (elf_getshdrstrndx(elf,&shstrndx) < 0) {
304 #else
305  if (elf_getshstrndx(elf,&shstrndx) < 0) {
306 #endif
307  verror("cannot get section header string table index\n");
308  return -1;
309  }
310 
311  scn = NULL;
312  while ((scn = elf_nextscn(elf,scn)) != NULL) {
313  shdr = gelf_getshdr(scn,&shdr_mem);
314 
315  if (shdr && shdr->sh_size > 0) {
316  name = elf_strptr(elf,shstrndx,shdr->sh_name);
317 
318  if (strcmp(name,".dynamic") == 0) {
320  "found %s section (%d); ELF file is dynamic\n",
321  name,shdr->sh_size);
322  return 1;
323  }
324  }
325  }
326 
327  vdebug(2,LA_DEBUG,LF_ELF,"ELF file is static\n");
328  return 0;
329 }
330 
332  char *elf_filename) {
333  Elf_Scn *scn = NULL;
334  size_t shstrndx;
335  GElf_Ehdr ehdr_mem;
336  GElf_Ehdr *ehdr;
337  Ebl *ebl;
338  Elf_Data *edata;
339  unsigned int i;
340  int j,k;
341  Word_t nextstart = -1;
342  Word_t tmpstart = -1;
343  Word_t start = -1;
344  Word_t end = -1;
345  int class;
346  char *name;
347  GElf_Shdr shdr_mem;
348  GElf_Shdr *shdr;
349  unsigned int nsyms;
350  GElf_Sym sym_mem;
351  GElf_Sym *sym;
352  char *symname;
353  unsigned char stt;
354  struct symbol *symbol;
355  GElf_Shdr *sections = NULL;
356  struct array_list *ral;
357  struct clf_range_data *crd;
358  struct array_list *tmp_ral;
359  struct clf_range_data *tmp_crd;
360  struct symbol *tmp_symbol;
361  struct clf_range_data *gcrd;
362 
363  if (!(ehdr = gelf_getehdr(elf,&ehdr_mem))) {
364  verror("cannot read ELF header: %s",elf_errmsg(-1));
365  return -1;
366  }
367 
368  ebl = ebl_openbackend(elf);
369  if (ebl == NULL) {
370  verror("cannot create EBL handle: %s",strerror(errno));
371  return -1;
372  }
373 
374  class = gelf_getclass(elf);
375 
376 #if _INT_ELFUTILS_VERSION >= 152
377  if (elf_getshdrstrndx(elf,&shstrndx) < 0) {
378 #else
379  if (elf_getshstrndx(elf,&shstrndx) < 0) {
380 #endif
381  verror("cannot get section header string table index\n");
382  goto errout;
383  }
384 
385  /* Scan for strtab section */
386  scn = NULL;
387  while ((scn = elf_nextscn(elf,scn)) != NULL) {
388  shdr = gelf_getshdr(scn,&shdr_mem);
389 
390  if (shdr && shdr->sh_size > 0 && shdr->sh_type == SHT_STRTAB) {
391  name = elf_strptr(elf,shstrndx,shdr->sh_name);
392 
393  if (strcmp(name,".strtab") != 0)
394  continue;
395 
397  "found .strtab section in ELF file %s\n",
398  elf_filename);
399 
400  edata = elf_rawdata(scn,NULL);
401  if (!edata || !edata->d_size || !edata->d_buf) {
402  verror("cannot get data for valid section %s in %s: %s",
403  name,elf_filename,elf_errmsg(-1));
404  goto errout;
405  }
406 
407  debugfile->elf_strtablen = edata->d_size;
408  debugfile->elf_strtab = malloc(edata->d_size);
409  memcpy(debugfile->elf_strtab,edata->d_buf,edata->d_size);
410  break;
411  }
412  }
413 
414  if (!debugfile->elf_strtab) {
415  vwarn("could not find .strtab for ELF file %s; cannot load .symtab!\n",
416  elf_filename);
417  goto errout;
418  }
419 
420  /*
421  * Now scan all the section headers and build up a simple array.
422  */
423  sections = (GElf_Shdr *)calloc(ehdr->e_shnum,sizeof(GElf_Shdr));
424 
425  for (i = 0; i < ehdr->e_shnum; ++i) {
426  scn = elf_getscn(elf,i);
427  gelf_getshdr(scn,&sections[i]);
428  }
429 
430  /* Now rescan for symtab section */
431  scn = NULL;
432  while ((scn = elf_nextscn(elf,scn)) != NULL) {
433  shdr = gelf_getshdr(scn,&shdr_mem);
434 
435  if (!shdr || shdr->sh_size <= 0 || shdr->sh_type != SHT_SYMTAB)
436  continue;
437 
438  name = elf_strptr(elf,shstrndx,shdr->sh_name);
439 
440  if (strcmp(name,".symtab") != 0)
441  continue;
442 
443  vdebug(2,LA_DEBUG,LF_ELF,"found .symtab section in ELF file %s\n",elf_filename);
444 
445  edata = elf_getdata(scn,NULL);
446  if (!edata || !edata->d_size || !edata->d_buf) {
447  verror("cannot get data for valid section %s in %s: %s",
448  name,elf_filename,elf_errmsg(-1));
449  goto errout;
450  }
451 
452  nsyms = edata->d_size / (class == ELFCLASS32 ? sizeof (Elf32_Sym) \
453  : sizeof (Elf64_Sym));
454 
455  vdebug(2,LA_DEBUG,LF_DWARF,".symtab section in ELF file %s has %d symbols\n",
456  elf_filename,nsyms);
457 
458  /* Load the symtab */
459  for (i = 0; i < nsyms; ++i) {
460  sym = gelf_getsym(edata,i,&sym_mem);
461  if (sym->st_name >= debugfile->elf_strtablen) {
462  vwarn("skipping ELF symbol with bad name strtab idx %d\n",
463  (int)sym->st_name);
464  continue;
465  }
466 
467  stt = GELF_ST_TYPE(sym->st_info);
468 
469  /*
470  * If the symbol type is NOTYPE, check to see which
471  * section the symbol is in, and try to dynamically
472  * "set" the type to STT_OBJECT or STT_FUNC. This will
473  * result in symbols that should not be in the ELF
474  * symtab, probably, but hopefully it will reduce the
475  * amount of missing symbols in our ELF symtab.
476  */
477  if (stt == STT_NOTYPE && sym->st_shndx < ehdr->e_shnum) {
478  if (sections[sym->st_shndx].sh_flags & SHF_EXECINSTR)
479  stt = STT_FUNC;
480  else if (sections[sym->st_shndx].sh_flags & SHF_ALLOC)
481  stt = STT_OBJECT;
482  }
483 
484  if (!(stt == STT_OBJECT || stt == STT_COMMON || stt == STT_TLS
485  || stt == STT_FUNC))
486  /* Skip all non-code symbols */
487  continue;
488 
489 #ifdef DWDEBUG_USE_STRTAB
490  symname = &debugfile->elf_strtab[sym->st_name];
491 #else
492  symname = strdup(&debugfile->elf_strtab[sym->st_name]);
493 #endif
494 
495  symbol = symbol_create(debugfile->elf_symtab,(SMOFFSET)i,symname,
496  (stt == STT_OBJECT || stt == STT_TLS
497  || stt == STT_COMMON) \
498  ? SYMBOL_TYPE_VAR : SYMBOL_TYPE_FUNCTION,
500 
501  if (GELF_ST_BIND(sym->st_info) == STB_GLOBAL
502  || GELF_ST_BIND(sym->st_info) == STB_WEAK)
503  symbol->isexternal = 1;
504 
505  symbol->size.bytes = sym->st_size;
506  symbol->size_is_bytes = 1;
507 
508  symbol->base_addr = (ADDR)sym->st_value;
509  symbol->has_base_addr = 1;
510 
511  symtab_insert(debugfile->elf_symtab,symbol,0);
512 
513  /*
514  * Insert into debugfile->addresses IF the hashtable is
515  * empty (i.e., if we load the symtab first, before the
516  * debuginfo file), or if there is not anything already
517  * at this location. We want debuginfo symbols to trump
518  * ELF symbols in this table.
519  */
520  if (g_hash_table_size(debugfile->addresses) == 0
521  || !g_hash_table_lookup(debugfile->addresses,
522  (gpointer)symbol->base_addr))
523  g_hash_table_insert(debugfile->addresses,
524  (gpointer)symbol->base_addr,
525  (gpointer)symbol);
526 
527  if (symbol->base_addr != 0)
528  clrange_add(&debugfile->elf_ranges,symbol->base_addr,
529  symbol->base_addr + symbol->size.bytes,symbol);
530  }
531 
532  /* Now, go through all the address ranges and update their sizes
533  * based on the following range's address -- this is
534  * definitely possibly wrong sometimes. Could be wrong!
535  *
536  * The idea is, for any 0-length isexternal (GLOBAL ELF sym)
537  * function symbol, don't just look for the next symbol; look
538  * for the next global function symbol (or end of section).
539  *
540  * (This strategy is informed by how the Linux kernel does
541  * its i386 asm files; "functions" are declared global;
542  * labels are not, so they appear as LOCAL ELF symbols.)
543  *
544  * This will hopefully will allow disassembly of non-DWARF
545  * functions -- since we guess their length here. Could be
546  * wrong sometimes.
547  *
548  * XXX: one thing that will almost certainly be wrong is
549  * that we are not checking to make sure the guessed length
550  * is still in the same section as the symbol :).
551  */
552  nextstart = 0;
553  ral = clrange_find_next_inc(&debugfile->elf_ranges,nextstart);
554  while (ral) {
555  /*
556  * Go through each crd (symbol + metadata) at this start
557  * address, and if the CRD is 0-length, try to find the next
558  * symbol.
559  *
560  * One optimization (maybe) we *chould* do is if any symbols
561  * on the list are nonzero-length, just make the symbols
562  * that are 0-length be the value of the nonzero length, if
563  * their attributes match.
564  */
565  for (j = 0; j < array_list_len(ral); ++j) {
566  crd = (struct clf_range_data *)array_list_item(ral,j);
567  symbol = (struct symbol *)CLRANGE_DATA(crd);
568  /* Doesn't matter which crd we take the next start value
569  * from; they are all the same.
570  */
571  nextstart = start = CLRANGE_START(crd);
572  end = CLRANGE_END(crd);
573 
575  "checking end of ELF symbol %s (0x%"PRIxADDR","
576  "0x%"PRIxADDR")\n",
577  symbol_get_name(symbol),
578  CLRANGE_START(crd),CLRANGE_END(crd));
579 
580  if (start != end)
581  continue;
582 
583  /*
584  * Find the next nearest start range, such that
585  * attributes match.
586  *
587  * If the 0-length *function* symbol is global, and the
588  * next symbol is NOT global, we need to try to find the
589  * next global symbol!
590  */
591  if (SYMBOL_IS_FUNCTION(symbol) && symbol->isexternal) {
592  gcrd = NULL;
593  tmpstart = start;
594  while ((tmp_ral = \
595  clrange_find_next_exc(&debugfile->elf_ranges,
596  tmpstart))) {
597  /* Need to find *any* global symbol at this ral,
598  * so check the whole list!
599  */
600  for (k = 0; k < array_list_len(tmp_ral); ++k) {
601  tmp_crd = (struct clf_range_data *) \
602  array_list_item(tmp_ral,k);
603  tmp_symbol = (struct symbol *)CLRANGE_DATA(tmp_crd);
604  if (tmp_symbol->isexternal) {
605  gcrd = tmp_crd;
606  break;
607  }
608 
609  /* Doesn't matter which one; all same. */
610  tmpstart = CLRANGE_START(tmp_crd);
611  }
612 
613  if (gcrd)
614  break;
615  }
616 
617  if (!gcrd) {
618  vwarn("could not find next global symbol after %s;"
619  " not updating 0-length GLOBAL!\n",
620  symbol_get_name(symbol));
621  goto lcontinue;
622  }
623 
625  "updating 0-length GLOBAL symbol %s to"
626  " 0x%"PRIxADDR",0x%"PRIxADDR"\n",
627  symbol_get_name(symbol),start,CLRANGE_START(gcrd));
628 
629  clrange_update_end(&debugfile->elf_ranges,start,
630  CLRANGE_START(gcrd),symbol);
631 
632  symbol->size.bytes = CLRANGE_START(gcrd) - start;
633  symbol->size_is_bytes = 1;
634  symbol->guessed_size = 1;
635  }
636  else {
637  tmp_ral = clrange_find_next_exc(&debugfile->elf_ranges,start);
638  if (!tmp_ral) {
639  vwarn("could not find a next range after %s;"
640  " not updating 0-length symbol!\n",
641  symbol_get_name(symbol));
642  goto lcontinue;
643  }
644 
645  /* Just take the first one! */
646  gcrd = (struct clf_range_data *)array_list_item(tmp_ral,0);
647 
649  "updating 0-length symbol %s to 0x%"PRIxADDR","
650  "0x%"PRIxADDR"\n",
651  symbol_get_name(symbol),start,CLRANGE_START(gcrd));
652 
653  clrange_update_end(&debugfile->elf_ranges,start,
654  CLRANGE_START(gcrd),symbol);
655 
656  symbol->size.bytes = CLRANGE_START(gcrd) - start;
657  symbol->size_is_bytes = 1;
658  symbol->guessed_size = 1;
659  }
660  }
661 
662  lcontinue:
663  ral = clrange_find_next_exc(&debugfile->elf_ranges,nextstart);
664  }
665  }
666 
667 #ifndef DWDEBUG_USE_STRTAB
668  /*
669  * Only save elf_strtab if we're gonna use it.
670  */
671  if (debugfile->elf_strtab) {
672  free(debugfile->elf_strtab);
673  debugfile->elf_strtablen = 0;
674  debugfile->elf_strtab = NULL;
675  }
676 #endif
677 
678  out:
679  if (sections)
680  free(sections);
681  ebl_closebackend(ebl);
682  return 0;
683 
684  errout:
685  if (sections)
686  free(sections);
687  if (debugfile->elf_strtab)
688  free(debugfile->elf_strtab);
689  ebl_closebackend(ebl);
690  return -1;
691 }
Word_t start
Definition: clfit.h:37
union symbol::@7 size
int elf_get_debuginfo_info(Elf *elf, int *has_debuginfo_saveptr, char **buildid_saveptr, char **gnu_debuglinkfile_saveptr, uint32_t *gnu_debuglinkfile_crc_saveptr)
Definition: debug_elf.c:120
struct symbol * symbol_create(symbol_type_t symtype, symbol_source_t source, char *name, int name_copy, SMOFFSET offset, load_type_t loadtype, struct scope *scope)
Definition: debug.c:2550
unsigned int guessed_size
Definition: dwdebug_priv.h:839
static uint64_t unsigned int i
unsigned int isexternal
Definition: dwdebug_priv.h:839
unsigned int size_is_bytes
Definition: dwdebug_priv.h:839
int elf_is_dynamic_exe(Elf *elf)
Definition: debug_elf.c:295
int32_t SMOFFSET
Definition: common.h:100
#define verror(format,...)
Definition: log.h:30
#define vwarn(format,...)
Definition: log.h:33
#define ADDRMAX
Definition: common.h:74
void free(void *ptr)
Definition: debugserver.c:207
Definition: log.h:124
Definition: log.h:69
struct array_list * clrange_find_next_inc(clrange_t *clf, Word_t index)
Definition: clfit.c:481
debugfile_type_t
Definition: dwdebug.h:770
#define CLRANGE_DATA(crd)
Definition: clfit.h:45
int clrange_update_end(clrange_t *clf, Word_t start, Word_t end, void *data)
Definition: clfit.c:221
#define vdebug(devel, areas, flags, format,...)
Definition: log.h:302
#define CLRANGE_END(crd)
Definition: clfit.h:44
#define CLRANGE_START(crd)
Definition: clfit.h:43
void * calloc(size_t nmemb, size_t size)
Definition: debugserver.c:200
Definition: log.h:135
debugfile_type_t elf_get_debugfile_type_t(Elf *elf)
Definition: debug_elf.c:47
uint32_t ADDR
Definition: common.h:64
int debugfile_load_elfsymtab(struct debugfile *debugfile, Elf *elf, char *elf_filename)
Definition: debug_elf.c:331
uint32_t bytes
Definition: dwdebug_priv.h:901
#define PRIxADDR
Definition: common.h:67
GHashTable * addresses
Definition: dwdebug.h:965
char * symbol_get_name(struct symbol *symbol)
Definition: debug.c:2587
void * malloc(size_t size)
Definition: debugserver.c:214
int elf_get_arch_info(Elf *elf, int *wordsize, int *endian)
Definition: debug_elf.c:251
int clrange_add(clrange_t *clf, Word_t start, Word_t end, void *data)
Definition: clfit.c:104
int elf_get_base_addrs(Elf *elf, ADDR *base_virt_addr_saveptr, ADDR *base_phys_addr_saveptr)
Definition: debug_elf.c:67
struct array_list * clrange_find_next_exc(clrange_t *clf, Word_t index)
Definition: clfit.c:494