ROSE  0.9.6a
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ElfSymbolTable.C
Go to the documentation of this file.
1 /* ELF Symbol Tables (SgAsmElfSymbolSection and related classes) */
2 #include "sage3basic.h"
3 #include "stringify.h"
4 
5 using namespace rose;
6 
8 void
10 {
11  ROSE_ASSERT(symtab!=NULL);
12  SgAsmElfStringSection *strsec = dynamic_cast<SgAsmElfStringSection*>(symtab->get_linked_section());
13  ROSE_ASSERT(strsec!=NULL);
14 
15  set_name(new SgAsmStoredString(strsec->get_strtab(), 0));
16 
17  ROSE_ASSERT(symtab->get_symbols()!=NULL);
18  symtab->get_symbols()->get_symbols().push_back(this);
19  ROSE_ASSERT(symtab->get_symbols()->get_symbols().size()>0);
20  set_parent(symtab->get_symbols());
21 
22  set_st_info(0);
23  set_st_res1(0);
24  set_st_shndx(0);
25  set_st_size(0);
26 }
27 
29 void
31 {
32  p_st_info = ByteOrder::disk_to_host(sex, disk->st_info);
33  p_st_res1 = ByteOrder::disk_to_host(sex, disk->st_res1);
34  p_st_shndx = ByteOrder::disk_to_host(sex, disk->st_shndx);
35  p_st_size = ByteOrder::disk_to_host(sex, disk->st_size);
36 
37  p_value = ByteOrder::disk_to_host(sex, disk->st_value);
38  p_size = p_st_size;
39 
40  rose_addr_t name_offset = ByteOrder::disk_to_host(sex, disk->st_name);
41  get_name()->set_string(name_offset);
42 
43  parse_common();
44 }
45 
47 void
49 {
50  p_st_info = ByteOrder::disk_to_host(sex, disk->st_info);
51  p_st_res1 = ByteOrder::disk_to_host(sex, disk->st_res1);
52  p_st_shndx = ByteOrder::disk_to_host(sex, disk->st_shndx);
53  p_st_size = ByteOrder::disk_to_host(sex, disk->st_size);
54 
55  p_value = ByteOrder::disk_to_host(sex, disk->st_value);
56  p_size = p_st_size;
57 
58  rose_addr_t name_offset = ByteOrder::disk_to_host(sex, disk->st_name);
59  get_name()->set_string(name_offset);
60 
61  parse_common();
62 }
63 
64 void
66 {
67  /* Binding */
68  switch (get_elf_binding()) {
69  case STB_LOCAL: p_binding = SYM_LOCAL; break;
70  case STB_GLOBAL: p_binding = SYM_GLOBAL; break;
71  case STB_WEAK: p_binding = SYM_WEAK; break;
72  default: p_binding = SYM_NO_BINDING; break;
73  }
74 
75  /* Type */
76  switch (get_elf_type()) {
77  case STT_NOTYPE: p_type = SYM_NO_TYPE; break;
78  case STT_OBJECT: p_type = SYM_DATA; break;
79  case STT_FUNC: p_type = SYM_FUNC; break;
80  case STT_SECTION: p_type = SYM_SECTION; break;
81  case STT_FILE: p_type = SYM_FILE; break;
82  case STT_COMMON: p_type = SYM_COMMON; break;
83  case STT_TLS: p_type = SYM_TLS; break;
84  case STT_IFUNC: p_type = SYM_IFUNC; break;
85  default: p_type = SYM_NO_TYPE; break;
86  }
87 
88  /* Definition state */
89  if (p_value || p_size) {
90  p_def_state = SYM_DEFINED;
91  } else if (p_name->get_string().size() > 0 || get_elf_type()) {
92  p_def_state = SYM_TENTATIVE;
93  } else {
94  p_def_state = SYM_UNDEFINED;
95  }
96 }
97 
98 void
99 SgAsmElfSymbol::dump(FILE *f, const char *prefix, ssize_t idx) const
100 {
101  dump(f, prefix, idx, NULL);
102 }
103 
104 std::string
106 {
107 #ifndef _MSC_VER
109 #else
110  ROSE_ASSERT(false);
111  return "";
112 #endif
113 }
114 
115 std::string
117 {
118 #ifndef _MSC_VER
120 #else
121  ROSE_ASSERT(false);
122  return "";
123 #endif
124 }
125 
126 
129 {
130  return (ElfSymBinding)(p_st_info >> 4);
131 }
132 
135 {
136  return (ElfSymType)(p_st_info & 0xf);
137 }
138 
140 void *
142 {
143  rose_addr_t st_name = p_name->get_offset();
144  ROSE_ASSERT(st_name!=SgAsmGenericString::unallocated);
145  ByteOrder::host_to_disk(sex, st_name, &(disk->st_name));
146  ByteOrder::host_to_disk(sex, p_st_info, &(disk->st_info));
147  ByteOrder::host_to_disk(sex, p_st_res1, &(disk->st_res1));
148  ByteOrder::host_to_disk(sex, p_st_shndx, &(disk->st_shndx));
149  ByteOrder::host_to_disk(sex, p_st_size, &(disk->st_size));
150  ByteOrder::host_to_disk(sex, get_value(), &(disk->st_value));
151  return disk;
152 }
153 void *
155 {
156  rose_addr_t st_name = p_name->get_offset();
157  ROSE_ASSERT(st_name!=SgAsmGenericString::unallocated);
158  ByteOrder::host_to_disk(sex, st_name, &(disk->st_name));
159  ByteOrder::host_to_disk(sex, p_st_info, &(disk->st_info));
160  ByteOrder::host_to_disk(sex, p_st_res1, &(disk->st_res1));
161  ByteOrder::host_to_disk(sex, p_st_shndx, &(disk->st_shndx));
162  ByteOrder::host_to_disk(sex, p_st_size, &(disk->st_size));
163  ByteOrder::host_to_disk(sex, get_value(), &(disk->st_value));
164  return disk;
165 }
166 
168 void
169 SgAsmElfSymbol::dump(FILE *f, const char *prefix, ssize_t idx, SgAsmGenericSection *section) const
170 {
171  char p[4096];
172  if (idx>=0) {
173  sprintf(p, "%sElfSymbol[%zd].", prefix, idx);
174  } else {
175  sprintf(p, "%sElfSymbol.", prefix);
176  }
177  const int w = std::max(1, DUMP_FIELD_WIDTH-(int)strlen(p));
178 
179  SgAsmGenericSymbol::dump(f, p, -1);
180 
181  fprintf(f, "%s%-*s = %u", p, w, "st_info", p_st_info);
182  fprintf(f, " (%s %s)\n",to_string(get_elf_binding()).c_str(),to_string(get_elf_type()).c_str());
183  fprintf(f, "%s%-*s = %u\n", p, w, "st_res1", p_st_res1);
184  fprintf(f, "%s%-*s = %"PRIu64"\n", p, w, "st_size", p_st_size);
185 
186  if (section && section->get_id() == (int)p_st_shndx) {
187  fprintf(f, "%s%-*s = [%d] \"%s\"\n", p, w, "st_shndx", section->get_id(), section->get_name()->get_string(true).c_str());
188  } else {
189  fprintf(f, "%s%-*s = %u\n", p, w, "st_shndx", p_st_shndx);
190  }
191 
192  if (p_extra.size()>0) {
193  fprintf(f, "%s%-*s = %zu bytes\n", p, w, "extra", p_extra.size());
194  hexdump(f, 0, std::string(p)+"extra at ", p_extra);
195  }
196 }
197 
199 void
201 {
202  p_symbols = new SgAsmElfSymbolList;
203  p_symbols->set_parent(this);
204  ROSE_ASSERT(strings!=NULL);
205  p_linked_section = strings;
206 }
207 
211 {
213 
214  SgAsmElfFileHeader *fhdr = get_elf_header();
215  ROSE_ASSERT(fhdr!=NULL);
216  SgAsmElfSectionTableEntry *shdr = get_section_entry();
217  ROSE_ASSERT(shdr!=NULL);
218  SgAsmElfStringSection *strsec = dynamic_cast<SgAsmElfStringSection*>(get_linked_section());
219  ROSE_ASSERT(strsec!=NULL);
220 
221  size_t entry_size, struct_size, extra_size, nentries;
222  calculate_sizes(&entry_size, &struct_size, &extra_size, &nentries);
223  ROSE_ASSERT(entry_size==shdr->get_sh_entsize());
224 
225  /* Parse each entry */
226  for (size_t i=0; i<nentries; i++) {
227  SgAsmElfSymbol *entry=0;
228  if (4==fhdr->get_word_size()) {
229  entry = new SgAsmElfSymbol(this); /*adds symbol to this symbol table*/
231  read_content_local(i*entry_size, &disk, struct_size);
232  entry->parse(fhdr->get_sex(), &disk);
233  } else if (8==fhdr->get_word_size()) {
234  entry = new SgAsmElfSymbol(this); /*adds symbol to this symbol table*/
236  read_content_local(i*entry_size, &disk, struct_size);
237  entry->parse(fhdr->get_sex(), &disk);
238  } else {
239  throw FormatError("unsupported ELF word size");
240  }
241  if (extra_size>0)
242  entry->get_extra() = read_content_local_ucl(i*entry_size+struct_size, extra_size);
243  }
244  return this;
245 }
246 
249 SgAsmElfSymbolSection::calculate_sizes(size_t *entsize, size_t *required, size_t *optional, size_t *entcount) const
250 {
251  std::vector<size_t> extra_sizes;
252  for (size_t i=0; i<p_symbols->get_symbols().size(); i++)
253  extra_sizes.push_back(p_symbols->get_symbols()[i]->get_extra().size());
254  return calculate_sizes(sizeof(SgAsmElfSymbol::Elf32SymbolEntry_disk),
256  extra_sizes,
257  entsize, required, optional, entcount);
258 }
259 
269 void
271 {
272  for (size_t i=0; i < p_symbols->get_symbols().size(); i++) {
273  SgAsmElfSymbol *symbol = p_symbols->get_symbols()[i];
274 
275  /* Get bound section ptr */
276  if (symbol->get_st_shndx() > 0 && symbol->get_st_shndx() < 0xff00) {
277  SgAsmGenericSection *bound = get_file()->get_section_by_id(symbol->get_st_shndx());
278  ROSE_ASSERT(bound != NULL);
279  symbol->set_bound(bound);
280  }
281  }
282 }
283 
285 size_t
287 {
288  for (size_t i=0; i<p_symbols->get_symbols().size(); i++) {
289  if (p_symbols->get_symbols()[i]==symbol)
290  return i;
291  }
292  throw FormatError("symbol is not in symbol table");
293 }
294 
296 bool
298 {
299  bool reallocated = SgAsmElfSection::reallocate();
300 
301  /* Update parts of the section and segment tables not updated by superclass */
302  SgAsmElfSectionTableEntry *secent = get_section_entry();
303  if (secent)
304  secent->set_sh_type(p_is_dynamic ?
307  return reallocated;
308 }
309 
311 void
312 SgAsmElfSymbolSection::unparse(std::ostream &f) const
313 {
314  SgAsmElfFileHeader *fhdr = get_elf_header();
315  ROSE_ASSERT(fhdr);
316  ByteOrder::Endianness sex = fhdr->get_sex();
317 
318  size_t entry_size, struct_size, extra_size, nentries;
319  calculate_sizes(&entry_size, &struct_size, &extra_size, &nentries);
320 
321  /* Adjust the entry size stored in the ELF Section Table */
322  get_section_entry()->set_sh_entsize(entry_size);
323 
324  /* Write each entry's required part followed by the optional part */
325  for (size_t i=0; i<nentries; i++) {
328  void *disk=NULL;
329 
330  SgAsmElfSymbol *entry = p_symbols->get_symbols()[i];
331 
332  if (4==fhdr->get_word_size()) {
333  disk = entry->encode(sex, &disk32);
334  } else if (8==fhdr->get_word_size()) {
335  disk = entry->encode(sex, &disk64);
336  } else {
337  ROSE_ASSERT(!"unsupported word size");
338  }
339 
340  rose_addr_t spos = i * entry_size;
341  spos = write(f, spos, struct_size, disk);
342  if (entry->get_extra().size()>0) {
343  ROSE_ASSERT(entry->get_extra().size()<=extra_size);
344  write(f, spos, entry->get_extra());
345  }
346  }
347 
348  unparse_holes(f);
349 }
350 
352 void
353 SgAsmElfSymbolSection::dump(FILE *f, const char *prefix, ssize_t idx) const
354 {
355  char p[4096];
356  if (idx>=0) {
357  sprintf(p, "%sElfSymbolSection[%zd].", prefix, idx);
358  } else {
359  sprintf(p, "%sElfSymbolSection.", prefix);
360  }
361  const int w = std::max(1, DUMP_FIELD_WIDTH-(int)strlen(p));
362 
363  SgAsmElfSection::dump(f, p, -1);
364  fprintf(f, "%s%-*s = %s\n", p, w, "is_dynamic", p_is_dynamic ? "yes" : "no");
365  fprintf(f, "%s%-*s = %zu symbols\n", p, w, "ElfSymbol.size", p_symbols->get_symbols().size());
366  for (size_t i = 0; i < p_symbols->get_symbols().size(); i++) {
367  SgAsmGenericSection *section = get_file()->get_section_by_id(p_symbols->get_symbols()[i]->get_st_shndx());
368  p_symbols->get_symbols()[i]->dump(f, p, i, section);
369  }
370 
371  if (variantT() == V_SgAsmElfSymbolSection) //unless a base class
372  hexdump(f, 0, std::string(p)+"data at ", p_data);
373 }