ROSE  0.9.6a
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ElfDynamicLinking.C
Go to the documentation of this file.
1 /* ELF Dynamic Linking (SgAsmElfDynamicSection and related classes) */
2 #include "sage3basic.h"
3 #include "stringify.h"
4 
5 using namespace rose;
6 
8 void
10 {
11  ROSE_ASSERT(dynsec!=NULL);
12 
13  set_name(NULL); /*only defined for DT_NEEDED entries; see SgAsmDynamicSection::parse*/
14 
15  ROSE_ASSERT(dynsec->get_entries()!=NULL);
16  dynsec->get_entries()->get_entries().push_back(this);
17  ROSE_ASSERT(dynsec->get_entries()->get_entries().size()>0);
18  set_parent(dynsec->get_entries());
19 }
20 
22 void
24 {
25  p_d_tag = (EntryType)ByteOrder::disk_to_host(sex, disk->d_tag);
26  p_d_val = ByteOrder::disk_to_host(sex, disk->d_val);
27 }
28 void
30 {
31  p_d_tag = (EntryType)ByteOrder::disk_to_host(sex, disk->d_tag);
32  p_d_val = ByteOrder::disk_to_host(sex, disk->d_val);
33 }
34 
36 void *
38 {
39  ByteOrder::host_to_disk(sex, p_d_tag, &(disk->d_tag));
40  ByteOrder::host_to_disk(sex, p_d_val.get_rva(), &(disk->d_val));
41  return disk;
42 }
43 void *
45 {
46  ByteOrder::host_to_disk(sex, p_d_tag, &(disk->d_tag));
47  ByteOrder::host_to_disk(sex, p_d_val.get_rva(), &(disk->d_val));
48  return disk;
49 }
50 
52 std::string
54 {
55 #ifndef _MSC_VER
57 #else
58  ROSE_ASSERT(false);
59  return "";
60 #endif
61 
62 }
63 
65 void
67 {
68  if (name!=p_name) {
69  if (p_name) {
70  p_name->set_parent(NULL);
72  }
73  p_name = name;
74  if (p_name)
75  p_name->set_parent(this);
76  set_isModified(true);
77  }
78 }
79 
81 void
82 SgAsmElfDynamicEntry::dump(FILE *f, const char *prefix, ssize_t idx) const
83 {
84  char p[4096];
85  if (idx>=0) {
86  sprintf(p, "%sElfDynamicEntry[%zd].", prefix, idx);
87  } else {
88  sprintf(p, "%sElfDynamicEntry.", prefix);
89  }
90  const int w = std::max(1, DUMP_FIELD_WIDTH-(int)strlen(p));
91 
92  char label[256];
93  strcpy(label, to_string(p_d_tag).c_str());
94  for (char *s=label; *s; s++) *s = tolower(*s);
95 
96  fprintf(f, "%s%-*s = %s", p, w, label, p_d_val.to_string().c_str());
97  if (p_name)
98  fprintf(f, " \"%s\"", p_name->get_string(true).c_str());
99  fputc('\n', f);
100 
101  if (p_extra.size()>0) {
102  fprintf(f, "%s%-*s = %zu bytes\n", p, w, "extra", p_extra.size());
103  hexdump(f, 0, std::string(p)+"extra at ", p_extra);
104  }
105 }
106 
108 void
110 {
111  p_entries = new SgAsmElfDynamicEntryList;
112  p_entries->set_parent(this);
113  ROSE_ASSERT(strings!=NULL);
114  p_linked_section = strings;
115 }
116 
120 {
122 
123  SgAsmElfFileHeader *fhdr = get_elf_header();
124  ROSE_ASSERT(fhdr);
125  SgAsmElfSectionTableEntry *shdr = get_section_entry();
126  ROSE_ASSERT(shdr);
127  SgAsmElfStringSection *strsec = dynamic_cast<SgAsmElfStringSection*>(get_linked_section());
128  ROSE_ASSERT(strsec!=NULL);
129 
130  size_t entry_size, struct_size, extra_size, nentries;
131  calculate_sizes(&entry_size, &struct_size, &extra_size, &nentries);
132  ROSE_ASSERT(entry_size==shdr->get_sh_entsize());
133 
134  /* Parse each entry */
135  for (size_t i=0; i<nentries; i++) {
136  SgAsmElfDynamicEntry *entry=0;
137  if (4==fhdr->get_word_size()) {
138  entry = new SgAsmElfDynamicEntry(this);
140  read_content_local(i*entry_size, &disk, struct_size);
141  entry->parse(fhdr->get_sex(), &disk);
142  } else if (8==fhdr->get_word_size()) {
143  entry = new SgAsmElfDynamicEntry(this);
145  read_content_local(i*entry_size, &disk, struct_size);
146  entry->parse(fhdr->get_sex(), &disk);
147  } else {
148  throw FormatError("unsupported ELF word size");
149  }
150  if (extra_size>0)
151  entry->get_extra() = read_content_local_ucl(i*entry_size+struct_size, extra_size);
152 
153  /* Set name */
155  ROSE_ASSERT(entry->get_name()==NULL);
156  SgAsmStoredString *name = new SgAsmStoredString(strsec->get_strtab(), entry->get_d_val().get_rva());
157  entry->set_name(name);
158  name->set_parent(entry);
159 #if 1 /* FIXME: Do we really want this stuff duplicated in the AST? [RPM 2008-12-12] */
160  SgAsmStoredString *name2 = new SgAsmStoredString(strsec->get_strtab(), entry->get_d_val().get_rva());
161  fhdr->add_dll(new SgAsmGenericDLL(name2));
162 #endif
163  }
164  }
165  return this;
166 }
167 
170 SgAsmElfDynamicSection::calculate_sizes(size_t *entsize, size_t *required, size_t *optional, size_t *entcount) const
171 {
172  std::vector<size_t> extra_sizes;
173  for (size_t i=0; i<p_entries->get_entries().size(); i++)
174  extra_sizes.push_back(p_entries->get_entries()[i]->get_extra().size());
175  return calculate_sizes(sizeof(SgAsmElfDynamicEntry::Elf32DynamicEntry_disk),
177  extra_sizes,
178  entsize, required, optional, entcount);
179 }
180 
182 void
184 {
185  SgAsmElfFileHeader *fhdr = get_elf_header();
186  ROSE_ASSERT(fhdr!=NULL);
187 
188  for (size_t i=0; i<p_entries->get_entries().size(); i++) {
189  SgAsmElfDynamicEntry *entry = p_entries->get_entries()[i];
190  switch (entry->get_d_tag()) {
192  break;
222  /* d_val is relative to a section. We know that all ELF Sections (but perhaps not the ELF Segments) have been
223  * created by this time. */
224  ROSE_ASSERT(entry->get_d_val().get_section()==NULL);
225  SgAsmGenericSectionPtrList containers = fhdr->get_sections_by_rva(entry->get_d_val().get_rva());
226  SgAsmGenericSection *best = NULL;
227  for (SgAsmGenericSectionPtrList::iterator i=containers.begin(); i!=containers.end(); ++i) {
228  if ((*i)->is_mapped()) {
229  if ((*i)->get_mapped_preferred_rva()==entry->get_d_val().get_rva()) {
230  best = *i;
231  break;
232  } else if (!best) {
233  best = *i;
234  } else if ((*i)->get_mapped_size() < best->get_mapped_size()) {
235  best = *i;
236  }
237  }
238  }
239  if (best)
240  entry->set_d_val(rose_rva_t(entry->get_d_val().get_rva(), best));
241  break;
242  }
243  default:
244  break;
245  }
246  }
247 }
248 
250 bool
252 {
253  bool reallocated = SgAsmElfSection::reallocate();
254 
255  /* Update parts of the section and segment tables not updated by superclass */
256  SgAsmElfSectionTableEntry *secent = get_section_entry();
257  if (secent)
259  SgAsmElfSegmentTableEntry *segent = get_segment_entry();
260  if (segent)
262 
263  /* Update entries with name offsets. The name should point to the string table to which the dynamic section links. */
264  for (size_t i=0; i<p_entries->get_entries().size(); i++) {
265  SgAsmElfDynamicEntry *entry = p_entries->get_entries()[i];
266  if (entry->get_name()) {
267  SgAsmElfStringSection *strsec = dynamic_cast<SgAsmElfStringSection*>(get_linked_section());
268  ROSE_ASSERT(strsec);
269  SgAsmStoredString *stored_string = dynamic_cast<SgAsmStoredString*>(entry->get_name());
270  if (!stored_string || stored_string->get_strtab()!=strsec->get_strtab()) {
271  /* Not a stored string, or stored in the wrong string table. */
272  stored_string = new SgAsmStoredString(strsec->get_strtab(), entry->get_name()->get_string());
273  entry->get_name()->set_string(""); /*free old storage*/
274  entry->set_name(stored_string);
275  }
276  entry->set_d_val(entry->get_name()->get_offset());
277  }
278  }
279 
280  return reallocated;
281 }
282 
284 void
285 SgAsmElfDynamicSection::unparse(std::ostream &f) const
286 {
287  SgAsmElfFileHeader *fhdr = get_elf_header();
288  ROSE_ASSERT(fhdr);
289  ByteOrder::Endianness sex = fhdr->get_sex();
290 
291  size_t entry_size, struct_size, extra_size, nentries;
292  calculate_sizes(&entry_size, &struct_size, &extra_size, &nentries);
293 
294  /* Adjust the entry size stored in the ELF Section Table */
295  get_section_entry()->set_sh_entsize(entry_size);
296 
297  /* Write each entry's required part followed by the optional part */
298  for (size_t i=0; i<nentries; i++) {
301  void *disk = NULL;
302 
303  SgAsmElfDynamicEntry *entry = p_entries->get_entries()[i];
304 
305  if (4==fhdr->get_word_size()) {
306  disk = entry->encode(sex, &disk32);
307  } else if (8==fhdr->get_word_size()) {
308  disk = entry->encode(sex, &disk64);
309  } else {
310  ROSE_ASSERT(!"unsupported word size");
311  }
312 
313  rose_addr_t spos = i * entry_size;
314  spos = write(f, spos, struct_size, disk);
315  if (entry->get_extra().size()>0) {
316  ROSE_ASSERT(entry->get_extra().size()<=extra_size);
317  write(f, spos, entry->get_extra());
318  }
319  }
320 
321  unparse_holes(f);
322 }
323 
325 void
326 SgAsmElfDynamicSection::dump(FILE *f, const char *prefix, ssize_t idx) const
327 {
328  char p[4096];
329  if (idx>=0) {
330  sprintf(p, "%sDynamicSection[%zd].", prefix, idx);
331  } else {
332  sprintf(p, "%sDynamicSection.", prefix);
333  }
334 
335  SgAsmElfSection::dump(f, p, -1);
336 
337  for (size_t i=0; i<p_entries->get_entries().size(); i++) {
338  SgAsmElfDynamicEntry *ent = p_entries->get_entries()[i];
339  ent->dump(f, p, i);
340  dump_containing_sections(f, std::string(p)+"...", ent->get_d_val(), get_header()->get_sections()->get_sections());
341  }
342 
343  if (variantT() == V_SgAsmElfDynamicSection) //unless a base class
344  hexdump(f, 0, std::string(p)+"data at ", p_data);
345 }