ROSE  0.9.6a
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ElfSymbolVersion.C
Go to the documentation of this file.
1 /* ELF Symbol Versioning
2  *
3  * Symver Symbol Versioning (gnu extension) defines .gnu.version, .gnu.version_d, .gnu.version_r
4  * For more information see
5  * Sun: http://docs.sun.com/app/docs/doc/819-0690/chapter6-54676?a=view
6  * LSB: http://refspecs.freestandards.org/LSB_3.1.0/LSB-Core-generic/LSB-Core-generic/symversion.html
7  * Redhat: http://people.redhat.com/drepper/symbol-versioning
8  *
9  * Related SageIII classes:
10  * SgAsmElfSymverSection -- GNU Symvol Version Table; The ".gnu.version" section, subclass of SgAsmElfSection. This
11  * table is parallel to the list of symbols in the ".dynsym" section.
12  * SgAsmElfSymverEntry -- A single entry in an SgAsmElfSymverSection, usually an index into one of the other
13  * version tables, but some special values are also defined.
14  */
15 
16 #include "sage3basic.h"
17 
18 /*========================================================================================================================
19  * Methods for classes related to the GNU Symbol Version Table
20  *
21  * SgAsmElfSymverSection, contains a list of
22  * SgAsmElfSymverEntry
23  *======================================================================================================================== */
24 
26 void
28 {
29  ROSE_ASSERT(NULL != symver);
30 
31  ROSE_ASSERT(symver->get_entries()!=NULL);
32  symver->get_entries()->get_entries().push_back(this);
33  ROSE_ASSERT(symver->get_entries()->get_entries().size()>0);
34  set_parent(symver->get_entries());
35 
36  set_value(0);
37 }
38 
40 void
41 SgAsmElfSymverEntry::dump(FILE *f, const char *prefix, ssize_t idx) const
42 {
43  char p[4096];
44  if (idx>=0) {
45  sprintf(p, "%sElfSymverEntry[%zd].", prefix, idx);
46  } else {
47  sprintf(p, "%sElfSymver.", prefix);
48  }
49  const int w = std::max(1, DUMP_FIELD_WIDTH-(int)strlen(p));
50 
51  fprintf(f, "%s%-*s = %zu", p, w, "", p_value);
52  switch (p_value) {
53  case 0: fprintf(f, " (local)\n"); break;
54  case 1: fprintf(f, " (global)\n"); break;
55  default: fprintf(f, "\n"); break;
56  }
57 }
58 
60 void
62 {
64  p_entries->set_parent(this);
65 }
66 
70 {
72 
74  ROSE_ASSERT(fhdr!=NULL);
76  ROSE_ASSERT(shdr!=NULL);
77 
78  size_t entry_size, struct_size, extra_size, nentries;
79  calculate_sizes(&entry_size, &struct_size, &extra_size, &nentries);
80  ROSE_ASSERT(entry_size==shdr->get_sh_entsize());
81 
82  /* Parse each entry */
83  for (size_t i=0; i<nentries; ++i) {
84  SgAsmElfSymverEntry *entry=0;
85  entry = new SgAsmElfSymverEntry(this); /*adds symver to this symver table*/
86  uint16_t value;
87  read_content_local(i*entry_size, &value, struct_size);
88  entry->set_value(disk_to_host(fhdr->get_sex(), value));
89  }
90  return this;
91 }
92 
95 SgAsmElfSymverSection::calculate_sizes(size_t *entsize, size_t *required, size_t *optional, size_t *entcount) const
96 {
97  std::vector<size_t> extra_sizes;
98  return calculate_sizes(sizeof(uint16_t),
99  sizeof(uint16_t),
100  extra_sizes,
101  entsize, required, optional, entcount);
102 }
103 
105 void
106 SgAsmElfSymverSection::unparse(std::ostream &f) const
107 {
109  ROSE_ASSERT(fhdr);
110  ByteOrder::Endianness sex = fhdr->get_sex();
111 
112  size_t entry_size, struct_size, extra_size, nentries;
113  calculate_sizes(&entry_size, &struct_size, &extra_size, &nentries);
114 
115  /* Adjust the entry size stored in the ELF Section Table */
116  get_section_entry()->set_sh_entsize(entry_size);
117 
118  /* Write each entry's required part followed by the optional part */
119  for (size_t i=0; i<nentries; i++) {
120  uint16_t val;
121 
123  ByteOrder::host_to_disk(sex,entry->get_value(),&val);
124 
125  rose_addr_t spos = i * entry_size;
126  spos = write(f, spos, struct_size, &val);
127  }
128  unparse_holes(f);
129 }
130 
132 void
133 SgAsmElfSymverSection::dump(FILE *f, const char *prefix, ssize_t idx) const
134 {
135  char p[4096];
136  if (idx>=0) {
137  sprintf(p, "%sElfSymverSection[%zd].", prefix, idx);
138  } else {
139  sprintf(p, "%sElfSymverSection.", prefix);
140  }
141  const int w = std::max(1, DUMP_FIELD_WIDTH-(int)strlen(p));
142 
143  SgAsmElfSection::dump(f, p, -1);
144  fprintf(f, "%s%-*s = %zu entries\n", p, w, "entries.size", p_entries->get_entries().size());
145  for (size_t i = 0; i < p_entries->get_entries().size(); i++) {
146  p_entries->get_entries()[i]->dump(f, p, i);
147  }
148 
149  if (variantT() == V_SgAsmElfSymverSection) /*unless a base class*/
150  hexdump(f, 0, std::string(p)+"data at ", p_data);
151 }
152 
153 /*========================================================================================================================
154  * Methods for classes related to the GNU Symbol Version Definition Table
155  *
156  * SgAsmElfSymverDefinedSection, each containing a list of
157  * SgAsmElfSymverDefinedEntry, each containing a list of
158  * SgAsmElfSymverDefinedAux, each pointing to a name string
159  *======================================================================================================================== */
160 
162 void
164 {
166  ROSE_ASSERT(strsec!=NULL);
167 
168  SgAsmStoredString *name = new SgAsmStoredString(strsec->get_strtab(), 0);
169  set_name(name);
170  name->set_parent(this);
171 
172  ROSE_ASSERT(NULL != entry);
173  ROSE_ASSERT(NULL != entry->get_entries());
174 
175  entry->get_entries()->get_entries().push_back(this);
176  set_parent(entry->get_entries());
177 }
178 
182 void
183 SgAsmElfSymverDefinedAux::dump(FILE *f, const char *prefix, ssize_t idx) const
184 {
185  char p[4096];
186  if (idx>=0) {
187  sprintf(p, "%sElfSymverDefinedAux[%zd].", prefix, idx);
188  } else {
189  sprintf(p, "%sElfSymverDefinedAux.", prefix);
190  }
191  const int w = std::max(1, DUMP_FIELD_WIDTH-(int)strlen(p));
192 
193  fprintf(f, "%s%-*s = %s \n", p, w, "name", get_name()->get_string(true).c_str());
194 }
195 
197 void
199 {
200  rose_addr_t name_offset = disk_to_host(sex, disk->vda_name);
201  get_name()->set_string(name_offset);
202 }
203 
205 void *
207 {
208  rose_addr_t name_offset = p_name->get_offset();
209  ROSE_ASSERT(name_offset!=SgAsmGenericString::unallocated);
210  ByteOrder::host_to_disk(sex, name_offset, &(disk->vda_name));
211  return disk;
212 }
213 
215 void
217 {
218  ROSE_ASSERT(NULL != section);
219 
220  ROSE_ASSERT(NULL != section->get_entries());
221  section->get_entries()->get_entries().push_back(this);
222 
223  ROSE_ASSERT(section->get_entries()->get_entries().size()>0);
224  set_parent(section->get_entries());
225 
227  p_version = 0;
228  p_flags = 0;
229  p_index = 0;
230  p_hash = 0;
231 }
232 
234 void
236 {
237  p_version = disk_to_host(sex, disk->vd_version);
238  p_flags = disk_to_host(sex, disk->vd_flags);
239  p_index = disk_to_host(sex, disk->vd_ndx);
240  p_hash = disk_to_host(sex, disk->vd_hash);
241 }
242 
244 void *
246 {
248  ByteOrder::host_to_disk(sex, p_flags, &(disk->vd_flags));
249  ByteOrder::host_to_disk(sex, p_index, &(disk->vd_ndx));
250  ByteOrder::host_to_disk(sex, p_hash, &(disk->vd_hash));
251  return disk;
252 }
253 
255 void
256 SgAsmElfSymverDefinedEntry::dump(FILE *f, const char *prefix, ssize_t idx) const
257 {
258  char p[4096];
259  if (idx>=0) {
260  sprintf(p, "%sElfSymverDefinedEntry[%zd].", prefix, idx);
261  } else {
262  sprintf(p, "%sElfSymverDefinedEntry.", prefix);
263  }
264  const int w = std::max(1, DUMP_FIELD_WIDTH-(int)strlen(p));
265 
266  /* compact one-line-per-entry format */
267  if (0==idx)
268  fprintf(f, "%s%-*s %-8s %6s %10s %6s %-6s \n", p, w, "", "Version", "Index", "Hash", "Flags", "Names");
269  fprintf(f, "%s%-*s = 0x%04zx 0x%04zx 0x%08x 0x%04x", p, w, "", p_version, p_index, p_hash, (uint32_t)p_flags);
271  for (size_t i=0; i < entries.size(); ++i)
272  fprintf(f, "%s %s", 0==i?"":",", entries[i]->get_name()->get_string(true).c_str());
273  fputc('\n', f);
274 }
275 
277 void
279 {
281  p_entries->set_parent(this);
282 
283  ROSE_ASSERT(NULL != strings);
284  p_linked_section = strings;
285 }
286 
355 {
357 
359  ROSE_ASSERT(NULL!=fhdr);
361  ROSE_ASSERT(NULL!=shdr);
363  ROSE_ASSERT(NULL!=strsec);
364 
365  //size_t struct_size=sizeof(SgAsmElfSymverDefinedEntry::ElfSymverDefinedEntry_disk);
366 
367  rose_addr_t entry_addr=0;
368 
369  ByteOrder::Endianness sex=fhdr->get_sex();
370  /* Parse each entry*/
371  while (entry_addr < this->get_size()) {
372  SgAsmElfSymverDefinedEntry *entry=new SgAsmElfSymverDefinedEntry(this); /*adds SymverDefinedEntry to this*/
374  read_content_local(entry_addr, &entryDisk, sizeof(entryDisk));
375  entry->parse(sex, &entryDisk);
376 
377  /* These are relative to the start of this entry - i.e. entry_addr */
378  size_t num_aux = ByteOrder::disk_to_host(sex,entryDisk.vd_cnt);
379  size_t first_aux = ByteOrder::disk_to_host(sex,entryDisk.vd_aux);
380  size_t next_entry = ByteOrder::disk_to_host(sex,entryDisk.vd_next);
381 
382  rose_addr_t aux_addr=entry_addr+first_aux;
383  for (size_t i=0; i < num_aux; ++i) {
384  SgAsmElfSymverDefinedAux *aux=new SgAsmElfSymverDefinedAux(entry,this); /*adds SymverDefinedAux to this entry*/
386  read_content_local(aux_addr, &auxDisk, sizeof(auxDisk));
387  aux->parse(fhdr->get_sex(), &auxDisk);
388 
389  size_t next_aux = ByteOrder::disk_to_host(sex,auxDisk.vda_next);
390  if (next_aux == 0)
391  break;
392  aux_addr+=next_aux;
393  }
394 
395  if(next_entry == 0)
396  break;
397  entry_addr += next_entry;
398  }
399 
400  return this;
401 }
402 
405 SgAsmElfSymverDefinedSection::calculate_sizes(size_t *entsize, size_t *required, size_t *optional, size_t *entcount) const
406 {
407  size_t struct_size = sizeof(SgAsmElfSymverDefinedEntry::ElfSymverDefinedEntry_disk);
408  size_t aux_size = sizeof(SgAsmElfSymverDefinedAux::ElfSymverDefinedAux_disk);
409 
410  size_t extra_size = 0;
411  size_t entry_size = 0;
412  size_t nentries = get_entries()->get_entries().size();
413 
414  size_t total_size=0;
415  /* Entire entry should be at least large enough for the required part. */
416  entry_size = struct_size;
417 
418  /* Each entry has a list of 'aux' structures */
420  for (size_t i=0; i<nentries; ++i) {
421  size_t numAux = entries[i]->get_entries()->get_entries().size();
422  extra_size = std::max(extra_size, numAux * aux_size);
423  total_size += (struct_size + (numAux* aux_size));
424  }
425  /* Note - we could try to reach into the dynamic section for nentries */
426 
427  /* Return values */
428  if (entsize)
429  *entsize = entry_size;
430  if (required)
431  *required = struct_size;
432  if (optional)
433  *optional = extra_size;
434  if (entcount)
435  *entcount = nentries;
436  return total_size;
437 }
438 
440 void
442 {
444  ROSE_ASSERT(NULL != fhdr);
445  ByteOrder::Endianness sex = fhdr->get_sex();
446  size_t nentries;
447  calculate_sizes(NULL,NULL,NULL,&nentries);
448 
449  /* Adjust the entry size stored in the ELF Section Table */
450  get_section_entry()->set_sh_entsize(0); /*This doesn't have consistently sized entries, zero it*/
451 
452  /* Write each entry's required part followed by the optional part */
453  rose_addr_t entry_addr=0;/*as offset from section*/
454 
455  for (size_t ent=0; ent < nentries; ++ent) {
458  entry->encode(sex, &entryDisk);
459  const size_t entry_size=sizeof(SgAsmElfSymverDefinedEntry::ElfSymverDefinedEntry_disk);
460  const size_t aux_size=sizeof(SgAsmElfSymverDefinedAux::ElfSymverDefinedAux_disk);
461 
462  const SgAsmElfSymverDefinedAuxPtrList& auxes = entry->get_entries()->get_entries();
463  size_t num_aux = auxes.size();
464  size_t first_aux = entry_size;/*we always stick Aux's just after Entry*/
465  size_t next_entry = first_aux + ( num_aux * aux_size );
466  if (nentries -1 == ent) {
467  next_entry=0; /*final entry: next is null (0)*/
468  }
469 
470  ByteOrder::host_to_disk(sex, num_aux, &entryDisk.vd_cnt);
471  ByteOrder::host_to_disk(sex, first_aux, &entryDisk.vd_aux);
472  ByteOrder::host_to_disk(sex, next_entry, &entryDisk.vd_next);
473 
474  write(f, entry_addr, entry_size,&entryDisk);
475 
476  rose_addr_t aux_addr=entry_addr+first_aux;
477  for (size_t i=0; i < num_aux; ++i) {
478  SgAsmElfSymverDefinedAux *aux=auxes[i];
479 
481  aux->encode(sex, &auxDisk);
482 
483  size_t next_aux = aux_size;/*all auxes are contigious, so the next one is always just 8*/
484  if (num_aux-1 == i) {
485  next_aux=0;/* ... unless it is the final aux, then the next is null (0) */
486  }
487  ByteOrder::host_to_disk(sex,next_aux, &auxDisk.vda_next);
488 
489  write(f,aux_addr,aux_size, &auxDisk);
490  aux_addr+=next_aux;
491  }
492 
493  entry_addr += next_entry;
494  }
495 
496  unparse_holes(f);
497 }
498 
500 void
501 SgAsmElfSymverDefinedSection::dump(FILE *f, const char *prefix, ssize_t idx) const
502 {
503  char p[4096];
504  if (idx>=0) {
505  sprintf(p, "%sElfSymverDefinedSection[%zd].", prefix, idx);
506  } else {
507  sprintf(p, "%sElfSymverDefinedSection.", prefix);
508  }
509  const int w = std::max(1, DUMP_FIELD_WIDTH-(int)strlen(p));
510 
511  SgAsmElfSection::dump(f, p, -1);
512  fprintf(f, "%s%-*s = %zu entries\n", p, w, "ElfSymverDefined.size", p_entries->get_entries().size());
513  for (size_t i = 0; i < p_entries->get_entries().size(); i++) {
514  p_entries->get_entries()[i]->dump(f, p, i);
515  }
516 
517  if (variantT() == V_SgAsmElfSymverDefinedSection) /*unless a base class*/
518  hexdump(f, 0, std::string(p)+"data at ", p_data);
519 }
520 
521 /*========================================================================================================================
522  * Methods for section relating to the GNU Symbol Version Requirements Table.
523  *
524  * SgAsmElfSymverNeededSection, each containing a list of
525  * SgAsmElfSymverNeededEntry, each containing a list of
526  * SgAsmElfSymverNeededAux.
527  *======================================================================================================================== */
528 
531 void
533 {
535  ROSE_ASSERT(NULL != strsec);
536 
537  p_name = new SgAsmStoredString(strsec->get_strtab(), 0);
538  p_name->set_parent(this);
539 
540  ROSE_ASSERT(NULL != entry);
541  ROSE_ASSERT(NULL != entry->get_entries());
542  entry->get_entries()->get_entries().push_back(this);
543  set_parent(entry->get_entries());
544 
545  p_flags = 0;
546  p_other = 0;
547  p_hash = 0;
548 }
549 
553 void
554 SgAsmElfSymverNeededAux::dump(FILE *f, const char *prefix, ssize_t idx) const
555 {
556  char p[4096];
557  if (idx>=0) {
558  sprintf(p, "%sElfSymverNeededAux[%zd].", prefix, idx);
559  } else {
560  sprintf(p, "%sElfSymverNeededAux.", prefix);
561  }
562  const int w = std::max(1, DUMP_FIELD_WIDTH-(int)strlen(p));
563  fprintf(f, "%s%-*s = %04zx\n", p, w, "other", get_other());
564  fprintf(f, "%s%-*s = 0x%08x\n", p, w, "hash", get_hash());
565  fprintf(f, "%s%-*s = 0x%04x\n", p, w, "flags", get_flags());
566  fprintf(f, "%s%-*s = %s \n", p, w, "name", get_name()->get_string(true).c_str());
567 }
568 
570 void
572 {
576 
577  rose_addr_t name_offset = ByteOrder::disk_to_host(sex, disk->vna_name);
578  get_name()->set_string(name_offset);
579 }
580 
582 void *
584 {
588 
589  rose_addr_t name_offset = p_name->get_offset();
590  ROSE_ASSERT(name_offset!=SgAsmGenericString::unallocated);
591  ByteOrder::host_to_disk(sex, name_offset, &(disk->vna_name));
592  return disk;
593 }
594 
596 void
598 {
599  ROSE_ASSERT(NULL != section);
600  ROSE_ASSERT(NULL != section->get_entries());
601  section->get_entries()->get_entries().push_back(this);
602 
603  ROSE_ASSERT(section->get_entries()->get_entries().size()>0);
604  set_parent(section->get_entries());
605 
607  ROSE_ASSERT(NULL != strsec);
608 
609  SgAsmStoredString *name = new SgAsmStoredString(strsec->get_strtab(), 0);
610  set_file_name(name);
611  name->set_parent(this);
612 
614  p_entries->set_parent(this);
615 
616  p_version = 0;
617 }
618 
620 void
622 {
624  rose_addr_t file_offset = ByteOrder::disk_to_host(sex, disk->vn_file);
625  get_file_name()->set_string(file_offset);
626 }
627 
629 void *
631 {
633 
634  rose_addr_t file_offset = p_file_name->get_offset();
635  ROSE_ASSERT(file_offset!=SgAsmGenericString::unallocated);
636  ByteOrder::host_to_disk(sex, file_offset, &(disk->vn_file));
637 
638  return disk;
639 }
640 
642 void
643 SgAsmElfSymverNeededEntry::dump(FILE *f, const char *prefix, ssize_t idx) const
644 {
645  char p[4096];
646  if (idx>=0) {
647  sprintf(p, "%sElfSymverNeededEntry[%zd].", prefix, idx);
648  } else {
649  sprintf(p, "%sElfSymverNeededEntry.", prefix);
650  }
651  const int w = std::max(1, DUMP_FIELD_WIDTH-(int)strlen(p));
652 
653  /* compact one-line-per-entry format */
654  if (0==idx)
655  fprintf(f, "%s%-*s %-8s %-22s %6s %10s %6s %s\n", p, w, "", "Version", "File", "Other", "Hash", "Flags", "Name");
656  fprintf(f, "%s%-*s = 0x%04zx %s", p, w, "", p_version, get_file_name()->get_string(true).c_str());
658  if (entries.empty()) {
659  fprintf(f, "<no auxiliary entries>\n");
660  } else {
661  fprintf(f, "\n");
662  }
663  for (size_t i=0; i<entries.size(); ++i) {
664  SgAsmElfSymverNeededAux* aux = entries[i];
665  char auxname[32];
666  sprintf(auxname, "aux[%zu]", i);
667  fprintf(f, "%s%-*s = 0x%04zx 0x%08x 0x%04x %s\n", p, w, auxname,
668  aux->get_other(), aux->get_hash(), aux->get_flags(), aux->get_name()->get_string(true).c_str());
669  }
670  fprintf(f, "\n");
671 }
672 
674 void
676 {
678  p_entries->set_parent(this);
679 
680  ROSE_ASSERT(NULL != strings);
681  p_linked_section = strings;
682 }
683 
695 {
697 
699  ROSE_ASSERT(NULL!=fhdr);
701  ROSE_ASSERT(NULL!=shdr);
702 
703  //size_t struct_size=sizeof(SgAsmElfSymverNeededEntry::ElfSymverNeededEntry_disk);
704 
705  rose_addr_t entry_addr=0;
706 
707  ByteOrder::Endianness sex=fhdr->get_sex();
708  /* Parse each entry*/
709  while (entry_addr < this->get_size()) {
710  SgAsmElfSymverNeededEntry *entry=new SgAsmElfSymverNeededEntry(this); /*adds SymverNeededEntry to this*/
712  read_content_local(entry_addr, &entryDisk, sizeof(entryDisk));
713  entry->parse(sex, &entryDisk);
714 
715  /* These are relative to the start of this entry - i.e. entry_addr */
716  size_t num_aux = ByteOrder::disk_to_host(sex,entryDisk.vn_cnt);
717  size_t first_aux = ByteOrder::disk_to_host(sex,entryDisk.vn_aux);
718  size_t next_entry = ByteOrder::disk_to_host(sex,entryDisk.vn_next);
719 
720  rose_addr_t aux_addr=entry_addr+first_aux;
721  for (size_t i=0; i < num_aux; ++i) {
722  SgAsmElfSymverNeededAux *aux=new SgAsmElfSymverNeededAux(entry,this); /*adds SymverNeededAux to this entry*/
724  read_content_local(aux_addr, &auxDisk, sizeof(auxDisk));
725  aux->parse(sex, &auxDisk);
726 
727  size_t next_aux = ByteOrder::disk_to_host(sex,auxDisk.vna_next);
728  if (next_aux == 0)
729  break;
730  aux_addr+=next_aux;
731  }
732 
733  if(next_entry == 0)
734  break;
735  entry_addr += next_entry;
736  }
737  return this;
738 }
739 
742 SgAsmElfSymverNeededSection::calculate_sizes(size_t *entsize, size_t *required, size_t *optional, size_t *entcount) const
743 {
744  size_t struct_size = sizeof(SgAsmElfSymverNeededEntry::ElfSymverNeededEntry_disk);
745  size_t aux_size = sizeof(SgAsmElfSymverNeededAux::ElfSymverNeededAux_disk);
746 
747  size_t extra_size = 0;
748  size_t entry_size = 0;
749  size_t nentries = get_entries()->get_entries().size();
750 
751  size_t total_size=0;
752  /* Entire entry should be at least large enough for the required part. */
753  entry_size = struct_size;
754 
755  /* Each entry has a list of 'aux' structures */
757  for (size_t i=0; i<nentries; ++i) {
758  size_t numAux = entries[i]->get_entries()->get_entries().size();
759  extra_size = std::max(extra_size, numAux * aux_size);
760  total_size += (struct_size + (numAux* aux_size));
761  }
762  /* Note - we could try to reach into the dynamic section for nentries */
763 
764  /* Return values */
765  if (entsize)
766  *entsize = entry_size;
767  if (required)
768  *required = struct_size;
769  if (optional)
770  *optional = extra_size;
771  if (entcount)
772  *entcount = nentries;
773  return total_size;
774 }
775 
777 void
779 {
781  ROSE_ASSERT(NULL != fhdr);
782  ByteOrder::Endianness sex = fhdr->get_sex();
783  size_t nentries;
784  calculate_sizes(NULL,NULL,NULL,&nentries);
785 
786  /* Adjust the entry size stored in the ELF Section Table */
787  get_section_entry()->set_sh_entsize(0); /* This doesn't have consistently sized entries, zero it */
788 
789  /* Write each entry's required part followed by the optional part */
790  /* Parse each entry*/
791  rose_addr_t entry_addr=0; /* as offset from section */
792 
793  for (size_t ent=0; ent < nentries; ++ent) {
796  entry->encode(sex, &entryDisk);
797  const size_t entry_size=sizeof(SgAsmElfSymverNeededEntry::ElfSymverNeededEntry_disk);
798  const size_t aux_size=sizeof(SgAsmElfSymverNeededAux::ElfSymverNeededAux_disk);
799 
800  const SgAsmElfSymverNeededAuxPtrList& auxes = entry->get_entries()->get_entries();
801  size_t num_aux = auxes.size();
802  size_t first_aux = entry_size; /* we always stick Aux's just after Entry */
803  size_t next_entry = first_aux + ( num_aux * aux_size );
804  if (nentries -1 == ent) {
805  next_entry=0; /* final entry: next is null (0) */
806  }
807 
808  ByteOrder::host_to_disk(sex, num_aux, &entryDisk.vn_cnt);
809  ByteOrder::host_to_disk(sex, first_aux, &entryDisk.vn_aux);
810  ByteOrder::host_to_disk(sex, next_entry, &entryDisk.vn_next);
811 
812  write(f, entry_addr, entry_size,&entryDisk);
813 
814  rose_addr_t aux_addr=entry_addr+first_aux;
815  for (size_t i=0; i < num_aux; ++i) {
816  SgAsmElfSymverNeededAux *aux=auxes[i];
817 
819  aux->encode(sex, &auxDisk);
820 
821  size_t next_aux = aux_size;/* all auxes are contigious, so the next one is always just 8 */
822  if (num_aux-1 == i) {
823  next_aux=0; /* ... unless it is the final aux, then the next is null (0) */
824  }
825  ByteOrder::host_to_disk(sex,next_aux, &auxDisk.vna_next);
826 
827  write(f,aux_addr,aux_size, &auxDisk);
828  aux_addr+=next_aux;
829  }
830  entry_addr += next_entry;
831  }
832  unparse_holes(f);
833 }
834 
836 void
837 SgAsmElfSymverNeededSection::dump(FILE *f, const char *prefix, ssize_t idx) const
838 {
839  char p[4096];
840  if (idx>=0) {
841  sprintf(p, "%sElfSymverNeededSection[%zd].", prefix, idx);
842  } else {
843  sprintf(p, "%sElfSymverNeededSection.", prefix);
844  }
845  const int w = std::max(1, DUMP_FIELD_WIDTH-(int)strlen(p));
846 
847  SgAsmElfSection::dump(f, p, -1);
848  fprintf(f, "%s%-*s = %zu entries\n", p, w, "ElfSymverNeeded.size", p_entries->get_entries().size());
849  for (size_t i = 0; i < p_entries->get_entries().size(); i++) {
850  p_entries->get_entries()[i]->dump(f, p, i);
851  }
852 
853  if (variantT() == V_SgAsmElfSymverNeededSection) /*unless a base class*/
854  hexdump(f, 0, std::string(p)+"data at ", p_data);
855 }