ROSE  0.9.6a
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ElfRelocation.C
Go to the documentation of this file.
1 /* ELF Relocations (SgAsmElfRelocSection and related classes) */
2 #include "sage3basic.h"
3 #include "stringify.h"
4 
5 using namespace rose;
6 
8 void
10 {
11  ROSE_ASSERT(section->get_entries()!=NULL);
12  section->get_entries()->get_entries().push_back(this);
13  ROSE_ASSERT(section->get_entries()->get_entries().size()>0);
14  set_parent(section->get_entries());
15 }
16 
17 /* Parsers */
18 void
20 {
21  p_r_offset = disk_to_host(sex, disk->r_offset);
22  p_r_addend = disk_to_host(sex, disk->r_addend);
23  uint64_t info = disk_to_host(sex, disk->r_info);
24  p_sym = info >> 8;
25  p_type = (RelocType)(info & 0xff);
26 }
27 void
29 {
30  p_r_offset = disk_to_host(sex, disk->r_offset);
31  p_r_addend = disk_to_host(sex, disk->r_addend);
32  uint64_t info = disk_to_host(sex, disk->r_info);
33  p_sym = info >> 32;
34  p_type = (RelocType)(info & 0xffffffff);
35 }
36 void
38 {
39  p_r_offset = disk_to_host(sex, disk->r_offset);
40  p_r_addend = 0;
41  uint64_t info = disk_to_host(sex, disk->r_info);
42  p_sym = info >> 8;
43  p_type = (RelocType)(info & 0xff);
44 }
45 void
47 {
48  p_r_offset = disk_to_host(sex, disk->r_offset);
49  p_r_addend = 0;
50  uint64_t info = disk_to_host(sex, disk->r_info);
51  p_sym = info >> 32;
52  p_type = (RelocType)(info & 0xffffffff);
53 }
54 
55 /* Encode a native entry back into disk format */
56 void *
58 {
59  host_to_disk(sex, p_r_offset, &(disk->r_offset));
60  host_to_disk(sex, p_r_addend, &(disk->r_addend));
61  uint64_t info = (p_sym<<8) | (p_type & 0xff);
62  host_to_disk(sex, info, &(disk->r_info));
63  return disk;
64 }
65 void *
67 {
68  host_to_disk(sex, p_r_offset, &(disk->r_offset));
69  host_to_disk(sex, p_r_addend, &(disk->r_addend));
70  uint64_t info = ((uint64_t)p_sym<<32) | (p_type & 0xffffffff);
71  host_to_disk(sex, info, &(disk->r_info));
72  return disk;
73 }
74 void *
76 {
77  host_to_disk(sex, p_r_offset, &(disk->r_offset));
78  ROSE_ASSERT(0==p_r_addend);
79  uint64_t info = (p_sym<<8) | (p_type & 0xff);
80  host_to_disk(sex, info, &(disk->r_info));
81  return disk;
82 }
83 void *
85 {
86  host_to_disk(sex, p_r_offset, &(disk->r_offset));
87  ROSE_ASSERT(0==p_r_addend);
88  uint64_t info = ((uint64_t)p_sym<<32) | (p_type & 0xffffffff);
89  host_to_disk(sex, info, &(disk->r_info));
90  return disk;
91 }
92 
93 /* Change symbol to string. TODO, needs to handle multiple architectures [MCB] */
94 std::string
96 {
97 #ifndef _MSC_VER
98  return stringifySgAsmElfRelocEntryRelocType(get_type());
99 #else
100  ROSE_ASSERT(false);
101  return "";
102 #endif
103 }
104 
106 void
107 SgAsmElfRelocEntry::dump(FILE *f, const char *prefix, ssize_t idx, SgAsmElfSymbolSection *symtab) const
108 {
109  char p[4096];
110  if (idx>=0) {
111  sprintf(p, "%sElfRelocEntry[%zd]", prefix, idx);
112  } else {
113  sprintf(p, "%sElfRelocEntry", prefix);
114  }
115  const int w = std::max(1, DUMP_FIELD_WIDTH-(int)strlen(p));
116 
117  /* compact one-line-per-reloc format */
118  if (0==idx) {
119  fprintf(f, "%s%-*s %-10s %-20s %-10s %4s %-10s %s\n",
120  p, w, "", "Offset", "Type", "Addend", "Sym", "Value", "Name + Addend");
121  }
122 
123  /* Offset */
124  fprintf(f, "%s%-*s = 0x%08"PRIx64, p, w, "", p_r_offset);
125 
126  /* Type */
127  SgAsmGenericHeader* header = SageInterface::getEnclosingNode<SgAsmGenericHeader>(this);
128  if (header) {
129  fprintf(f, " %-20s", reloc_name().c_str());
130  } else {
131  fprintf(f, " 0x%02zx ", (size_t)p_type);
132  }
133 
134  /* Addend */
135  if (p_r_addend) {
136  fprintf(f, " 0x%08"PRIx64, p_r_addend);
137  } else {
138  fprintf(f, " %10s", "");
139  }
140 
141  /* Symbol index */
142  fprintf(f, " %4lu", p_sym);
143 
144  /* Symbol value and name */
145  if (!symtab) {
146  fprintf(f, " %10s <no symtab>", "");
147  } else if (p_sym>=symtab->get_symbols()->get_symbols().size()) {
148  fprintf(f, " %10s <out of range>", "");
149  } else {
150  SgAsmGenericSymbol *sym = symtab->get_symbols()->get_symbols()[p_sym];
151  fprintf(f, " 0x%08"PRIx64" %s", sym->get_value(), sym->get_name()->get_string(true).c_str());
152  }
153 
154  /* Addend in decimal */
155  if (p_r_addend)
156  fprintf(f, " + %"PRIu64, p_r_addend);
157  fputc('\n', f);
158 
159  /* Auxiliary data */
160  if (p_extra.size()>0) {
161  fprintf(f, "%s%-*s = %zu bytes\n", p, w, ".extra", p_extra.size());
162  hexdump(f, 0, std::string(p)+"extra at ", p_extra);
163  }
164 }
165 
167 void
169 {
170  p_entries = new SgAsmElfRelocEntryList;
171  p_entries->set_parent(this);
172  p_linked_section = symbols; // may be null
173  p_target_section = targetsec;
174 }
175 
179 {
181 
182  SgAsmElfFileHeader *fhdr = get_elf_header();
183  ROSE_ASSERT(fhdr);
184 
185  size_t entry_size, struct_size, extra_size, nentries;
186  calculate_sizes(&entry_size, &struct_size, &extra_size, &nentries);
187  ROSE_ASSERT(extra_size==0);
188 
189  /* Parse each entry */
190  for (size_t i=0; i<nentries; i++) {
191  SgAsmElfRelocEntry *entry = 0;
192  if (4==fhdr->get_word_size()) {
193  if (p_uses_addend) {
195  read_content_local(i*entry_size, &disk, struct_size);
196  entry = new SgAsmElfRelocEntry(this);
197  entry->parse(fhdr->get_sex(), &disk);
198  } else {
200  read_content_local(i*entry_size, &disk, struct_size);
201  entry = new SgAsmElfRelocEntry(this);
202  entry->parse(fhdr->get_sex(), &disk);
203  }
204  } else if (8==fhdr->get_word_size()) {
205  if (p_uses_addend) {
207  read_content_local(i*entry_size, &disk, struct_size);
208  entry = new SgAsmElfRelocEntry(this);
209  entry->parse(fhdr->get_sex(), &disk);
210  } else {
212  read_content_local(i*entry_size, &disk, struct_size);
213  entry = new SgAsmElfRelocEntry(this);
214  entry->parse(fhdr->get_sex(), &disk);
215  }
216  } else {
217  throw FormatError("unsupported ELF word size");
218  }
219  if (extra_size>0)
220  entry->get_extra() = read_content_local_ucl(i*entry_size+struct_size, extra_size);
221  }
222  return this;
223 }
224 
227 SgAsmElfRelocSection::calculate_sizes(size_t *entsize, size_t *required, size_t *optional, size_t *entcount) const
228 {
229  rose_addr_t retval=0;
230  std::vector<size_t> extra_sizes;
231  for (size_t i=0; i<p_entries->get_entries().size(); i++)
232  extra_sizes.push_back(p_entries->get_entries()[i]->get_extra().size());
233  if (p_uses_addend) {
234  retval = calculate_sizes(sizeof(SgAsmElfRelocEntry::Elf32RelaEntry_disk),
236  extra_sizes, entsize, required, optional, entcount);
237  } else {
238  retval = calculate_sizes(sizeof(SgAsmElfRelocEntry::Elf32RelEntry_disk),
240  extra_sizes, entsize, required, optional, entcount);
241  }
242  return retval;
243 }
244 
246 bool
248 {
249  bool reallocated = SgAsmElfSection::reallocate();
250 
251  /* Update parts of the section and segment tables not updated by superclass */
252  SgAsmElfSectionTableEntry *secent = get_section_entry();
253  if (secent)
254  secent->set_sh_type(p_uses_addend ?
257 
258  return reallocated;
259 }
260 
262 void
263 SgAsmElfRelocSection::unparse(std::ostream &f) const
264 {
265  SgAsmElfFileHeader *fhdr = get_elf_header();
266  ROSE_ASSERT(fhdr);
267  ByteOrder::Endianness sex = fhdr->get_sex();
268 
269  size_t entry_size, struct_size, extra_size, nentries;
270  calculate_sizes(&entry_size, &struct_size, &extra_size, &nentries);
271 
272  /* Adjust the entry size stored in the ELF Section Table */
273  get_section_entry()->set_sh_entsize(entry_size);
274 
275  /* Write each entry's required part followed by the optional part */
276  for (size_t i=0; i<nentries; i++) {
281  void *disk = NULL;
282 
283  SgAsmElfRelocEntry *entry = p_entries->get_entries()[i];
284 
285  if (4==fhdr->get_word_size()) {
286  if (p_uses_addend) {
287  disk = entry->encode(sex, &diska32);
288  } else {
289  disk = entry->encode(sex, &disk32);
290  }
291  } else if (8==fhdr->get_word_size()) {
292  if (p_uses_addend) {
293  disk = entry->encode(sex, &diska64);
294  } else {
295  disk = entry->encode(sex, &disk64);
296  }
297  } else {
298  ROSE_ASSERT(!"unsupported word size");
299  }
300 
301  rose_addr_t spos = i * entry_size;
302  spos = write(f, spos, struct_size, disk);
303 #if 0 /*FIXME: padding not supported here yet (RPM 2008-10-13)*/
304  if (entry->get_extra().size()>0) {
305  ROSE_ASSERT(entry->get_extra().size()<=extra_size);
306  write(f, spos, entry->get_extra());
307  }
308 #endif
309  }
310 
311  unparse_holes(f);
312 }
313 
315 void
316 SgAsmElfRelocSection::dump(FILE *f, const char *prefix, ssize_t idx) const
317 {
318  char p[4096];
319  if (idx>=0) {
320  sprintf(p, "%sRelocSection[%zd].", prefix, idx);
321  } else {
322  sprintf(p, "%sRelocSection.", prefix);
323  }
324  const int w = std::max(1, DUMP_FIELD_WIDTH-(int)strlen(p));
325 
326  SgAsmElfSection::dump(f, p, -1);
327  SgAsmElfSymbolSection *symtab = dynamic_cast<SgAsmElfSymbolSection*>(get_linked_section());
328  fprintf(f, "%s%-*s = %s\n", p, w, "uses_addend", p_uses_addend ? "yes" : "no");
329 
330  if (p_target_section) {
331  fprintf(f, "%s%-*s = [%d] \"%s\"\n", p, w, "target_section",
332  p_target_section->get_id(), p_target_section->get_name()->get_string(true).c_str());
333  } else {
334  fprintf(f, "%s%-*s = NULL\n", p, w, "target_section");
335  }
336 
337  for (size_t i=0; i<p_entries->get_entries().size(); i++) {
338  SgAsmElfRelocEntry *ent = p_entries->get_entries()[i];
339  ent->dump(f, p, i, symtab);
340  }
341 
342  if (variantT() == V_SgAsmElfRelocSection) //unless a base class
343  hexdump(f, 0, std::string(p)+"data at ", p_data);
344 }