PS2SDK
PS2 Homebrew Libraries
elflib.c
1 /*
2 # _____ ___ ____ ___ ____
3 # ____| | ____| | | |____|
4 # | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5 #-----------------------------------------------------------------------
6 # Copyright ps2dev - http://www.ps2dev.org
7 # Licenced under Academic Free License version 2.0
8 # Review ps2sdk README & LICENSE files for further details.
9 */
10 
11 #include "srxfixup_internal.h"
12 #include <errno.h>
13 #include <stdint.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 
18 static int is_in_range(unsigned int top, unsigned int size, unsigned int pos);
19 static void read_symtab(elf_file *elf, int sctindex, FILE *fp);
20 static void read_rel(elf_file *elf, int sctindex, FILE *fp);
21 static elf_mips_symbolic_data *read_mips_symbolic(FILE *fp);
22 static void renumber_a_symtab(elf_section *scp);
23 static void renumber_symtab(elf_file *elf);
24 static void write_symtab(elf_file *elf, int sctindex, FILE *fp);
25 static void write_rel(elf_file *elf, int sctindex, FILE *fp);
26 static void write_mips_symbolic(elf_mips_symbolic_data *sycb, unsigned int basepos, FILE *fp);
27 static void reorder_an_symtab(elf_file *elf, elf_section *scp);
28 static size_t search_string_table(const char *tbltop, size_t endindex, const char *str);
29 static void rebuild_a_symbol_name_strings(elf_section *scp);
30 static int comp_Elf_file_slot(const void *a1, const void *a2);
31 
32 elf_file *read_elf(const char *filename)
33 {
34  uint32_t ident;
35  elf_file *elf;
36  FILE *fp;
37 
38  fp = fopen(filename, "rb");
39  if ( !fp )
40  {
41  fprintf(stderr, "\"%s\" can't open (errno=%d)\n", filename, errno);
42  return 0;
43  }
44  elf = (elf_file *)calloc(1, sizeof(elf_file));
45  elf->ehp = (Elf32_Ehdr *)malloc(sizeof(Elf32_Ehdr));
46  if ( fread(elf->ehp, sizeof(Elf32_Ehdr), 1, fp) != 1 )
47  {
48  fprintf(stderr, "%s: Could not read ELF header (errno=%d)\n", filename, errno);
49  exit(1);
50  }
51  swapmemory(elf->ehp, "ccccccccccccccccsslllllssssss", 1);
52  ident = *(uint32_t *)elf->ehp->e_ident;
53  swapmemory(&ident, "l", 1);
54  if ( ident != 0x464C457F )
55  {
56  fprintf(stderr, "%s: not elf format\n", filename);
57  free(elf->ehp);
58  free(elf);
59  fclose(fp);
60  return 0;
61  }
62  if ( elf->ehp->e_ident[4] != ELFCLASS32 || elf->ehp->e_ident[5] != ELFDATA2LSB || elf->ehp->e_ident[6] != EV_CURRENT )
63  {
64  fprintf(stderr, "%s: Not 32-bit object or Not little endian or Invalid Elf version\n", filename);
65  free(elf->ehp);
66  free(elf);
67  fclose(fp);
68  return 0;
69  }
70  if ( elf->ehp->e_machine != EM_MIPS )
71  {
72  fprintf(stderr, "%s: not EM_MIPS\n", filename);
73  free(elf->ehp);
74  free(elf);
75  fclose(fp);
76  return 0;
77  }
78  if ( elf->ehp->e_phentsize && elf->ehp->e_phentsize != sizeof(Elf32_Phdr) )
79  {
80  fprintf(stderr, "%s: Unknown program header size\n", filename);
81  free(elf->ehp);
82  free(elf);
83  fclose(fp);
84  return 0;
85  }
86  if ( elf->ehp->e_shentsize && elf->ehp->e_shentsize != sizeof(Elf32_Shdr) )
87  {
88  fprintf(stderr, "%s: Unknown sectoin header size\n", filename);
89  free(elf->ehp);
90  free(elf);
91  fclose(fp);
92  return 0;
93  }
94  if ( elf->ehp->e_phnum && elf->ehp->e_phentsize )
95  {
96  signed int count_1;
97  unsigned int pos_1;
98  int i_1;
99 
100  count_1 = elf->ehp->e_phnum;
101  pos_1 = elf->ehp->e_phoff;
102  elf->php = (elf_proghead *)calloc(count_1, sizeof(elf_proghead));
103  fseek(fp, pos_1, SEEK_SET);
104  for ( i_1 = 0; count_1 > i_1; i_1 += 1 )
105  {
106  if ( fread(&elf->php[i_1], sizeof(Elf32_Phdr), 1, fp) != 1 )
107  {
108  fprintf(stderr, "%s: Could not read ELF program header (errno=%d)\n", filename, errno);
109  exit(1);
110  }
111  swapmemory(&elf->php[i_1], "llllllll", 1);
112  }
113  }
114  if ( elf->ehp->e_shnum && elf->ehp->e_shentsize )
115  {
116  signed int count_2;
117  unsigned int pos_2;
118  int i_2;
119  int i_3;
120  int i_4;
121 
122  pos_2 = elf->ehp->e_shoff;
123  count_2 = elf->ehp->e_shnum;
124  elf->scp = (elf_section **)calloc(count_2 + 1, sizeof(elf_section *));
125  fseek(fp, pos_2, SEEK_SET);
126  for ( i_2 = 0; count_2 > i_2; i_2 += 1 )
127  {
128  elf->scp[i_2] = (elf_section *)calloc(1, sizeof(elf_section));
129  if ( fread(elf->scp[i_2], sizeof(Elf32_Shdr), 1, fp) != 1 )
130  {
131  fprintf(stderr, "%s: Could not read ELF section header (errno=%d)\n", filename, errno);
132  exit(1);
133  }
134  swapmemory(elf->scp[i_2], "llllllllll", 1);
135  }
136  for ( i_3 = 0; count_2 > i_3; i_3 += 1 )
137  {
138  switch ( elf->scp[i_3]->shr.sh_type )
139  {
140 #pragma GCC diagnostic push
141 #pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
142  case SHT_RELA:
143  case SHT_REL:
144  elf->scp[i_3]->info = elf->scp[elf->scp[i_3]->shr.sh_info];
145  case SHT_SYMTAB:
146  case SHT_HASH:
147  case SHT_DYNAMIC:
148  case SHT_DYNSYM:
149  elf->scp[i_3]->link = elf->scp[elf->scp[i_3]->shr.sh_link];
150  break;
151 #pragma GCC diagnostic pop
152  default:
153  break;
154  }
155  if ( i_3 == elf->ehp->e_shstrndx )
156  {
157  elf->shstrptr = elf->scp[i_3];
158  }
159  }
160  for ( i_4 = 0;; i_4 += 1 )
161  {
162  unsigned int size;
163  unsigned int pos_3;
164 
165  if ( count_2 <= i_4 )
166  {
167  int i_5;
168  int i_6;
169  int i_7;
170  int i_8;
171 
172  for ( i_5 = 0; count_2 > i_5; i_5 += 1 )
173  {
174  unsigned int pos_4;
175 
176  pos_4 = elf->scp[i_5]->shr.sh_offset;
177  switch ( elf->scp[i_5]->shr.sh_type )
178  {
179  case SHT_SYMTAB:
180  case SHT_DYNSYM:
181  if ( pos_4 != 0 && elf->scp[i_5]->shr.sh_size )
182  {
183  fseek(fp, pos_4, SEEK_SET);
184  read_symtab(elf, i_5, fp);
185  }
186  break;
187  default:
188  break;
189  }
190  }
191  for ( i_6 = 0; count_2 > i_6; i_6 += 1 )
192  {
193  unsigned int pos_5;
194 
195  pos_5 = elf->scp[i_6]->shr.sh_offset;
196  if ( elf->scp[i_6]->shr.sh_type == SHT_REL && pos_5 != 0 && elf->scp[i_6]->shr.sh_size )
197  {
198  fseek(fp, pos_5, SEEK_SET);
199  read_rel(elf, i_6, fp);
200  }
201  }
202  for ( i_7 = 0; count_2 > i_7; i_7 += 1 )
203  {
204  elf->scp[i_7]->name =
205  strdup((elf->shstrptr != NULL) ? ((char *)&elf->shstrptr->data[elf->scp[i_7]->shr.sh_name]) : "");
206  }
207  for ( i_8 = 0; i_8 < elf->ehp->e_phnum; i_8 += 1 )
208  {
209  int d;
210  int s;
211 
212  switch ( elf->php[i_8].phdr.p_type )
213  {
214  case PT_LOAD:
215  elf->php[i_8].scp = (elf_section **)calloc(count_2, sizeof(elf_section *));
216  d = 0;
217  for ( s = 1; s < count_2; s += 1 )
218  {
219  unsigned int p_filesz;
220  unsigned int p_offset;
221 
222  p_offset = elf->php[i_8].phdr.p_offset;
223  p_filesz = elf->php[i_8].phdr.p_filesz;
224  switch ( elf->scp[s]->shr.sh_type )
225  {
226  case SHT_PROGBITS:
227  if (
228  is_in_range(p_offset, p_filesz, elf->scp[s]->shr.sh_offset)
229  || (!elf->scp[s]->shr.sh_size && elf->scp[s]->shr.sh_offset == p_filesz + p_offset) )
230  {
231  elf->php[i_8].scp[d] = elf->scp[s];
232  d += 1;
233  }
234  break;
235  case SHT_NOBITS:
236  if (
237  is_in_range(elf->php[i_8].phdr.p_vaddr, elf->php[i_8].phdr.p_memsz, elf->scp[s]->shr.sh_addr)
238  || (!elf->scp[s]->shr.sh_size && elf->scp[s]->shr.sh_offset == p_filesz + p_offset) )
239  {
240  elf->php[i_8].scp[d] = elf->scp[s];
241  d += 1;
242  }
243  break;
244  default:
245  break;
246  }
247  }
248  break;
249  case PT_MIPS_REGINFO:
250  elf->php[i_8].scp = (elf_section **)calloc(2, sizeof(elf_section *));
251  *elf->php[i_8].scp = search_section(elf, SHT_MIPS_REGINFO);
252  break;
253  case PT_SCE_IOPMOD:
254  elf->php[i_8].scp = (elf_section **)calloc(2, sizeof(elf_section *));
255  *elf->php[i_8].scp = search_section(elf, SHT_SCE_IOPMOD);
256  break;
257  case PT_SCE_EEMOD:
258  elf->php[i_8].scp = (elf_section **)calloc(2, sizeof(elf_section *));
259  *elf->php[i_8].scp = search_section(elf, SHT_SCE_EEMOD);
260  break;
261  default:
262  break;
263  }
264  }
265  // Workaround for malformed file: make distance between sh_addr agree with sh_offset
266  switch ( elf->ehp->e_type )
267  {
268  case ET_SCE_IOPRELEXEC:
269  case ET_SCE_IOPRELEXEC2:
270  case ET_SCE_EERELEXEC:
271  case ET_SCE_EERELEXEC2:
272  for ( i_8 = 0; i_8 < elf->ehp->e_phnum; i_8 += 1 )
273  {
274  int s;
275  elf_section **scp;
276 
277  switch ( elf->php[i_8].phdr.p_type )
278  {
279  case PT_LOAD:
280  scp = elf->php[i_8].scp;
281  for ( s = 1; scp[s]; s += 1 )
282  {
283  if ( scp[s]->shr.sh_type != SHT_NOBITS )
284  {
285  unsigned int addrdiff;
286  unsigned int offsetdiff;
287 
288  addrdiff = scp[s]->shr.sh_addr - scp[s - 1]->shr.sh_addr;
289  offsetdiff = scp[s]->shr.sh_offset - scp[s - 1]->shr.sh_offset;
290  if ( addrdiff != offsetdiff )
291  {
292  scp[s]->shr.sh_addr = scp[s - 1]->shr.sh_addr + offsetdiff;
293  }
294  }
295  }
296  break;
297  default:
298  break;
299  }
300  }
301  break;
302  default:
303  break;
304  }
305  return elf;
306  }
307  pos_3 = elf->scp[i_4]->shr.sh_offset;
308  size = elf->scp[i_4]->shr.sh_size;
309  if ( pos_3 != 0 && size != 0 )
310  {
311  fseek(fp, pos_3, SEEK_SET);
312  switch ( elf->scp[i_4]->shr.sh_type )
313  {
314  case SHT_PROGBITS:
315  case SHT_RELA:
316  case SHT_HASH:
317  case SHT_DYNAMIC:
318  case SHT_MIPS_REGINFO:
319  elf->scp[i_4]->data = (uint8_t *)malloc(size);
320  if ( fread(elf->scp[i_4]->data, size, 1, fp) != 1 )
321  {
322  fprintf(stderr, "%s: Could not read ELF section contents, (errno=%d)\n", filename, errno);
323  exit(1);
324  }
325  swapmemory(elf->scp[i_4]->data, "l", size >> 2);
326  break;
327  case SHT_SYMTAB:
328  case SHT_NOBITS:
329  case SHT_DYNSYM:
330  break;
331  case SHT_MIPS_DEBUG:
332  elf->scp[i_4]->data = (uint8_t *)read_mips_symbolic(fp);
333  break;
334  case SHT_SCE_IOPMOD:
335  elf->scp[i_4]->data = (uint8_t *)malloc(size);
336  if ( fread(elf->scp[i_4]->data, size, 1, fp) != 1 )
337  {
338  fprintf(stderr, "%s: Could not read ELF section contents (errno=%d)\n", filename, errno);
339  exit(1);
340  }
341  swapmemory(elf->scp[i_4]->data, "lllllls", 1);
342  break;
343  case SHT_SCE_EEMOD:
344  elf->scp[i_4]->data = (uint8_t *)malloc(size);
345  if ( fread(elf->scp[i_4]->data, size, 1, fp) != 1 )
346  {
347  fprintf(stderr, "%s: Could not read ELF section contents (errno=%d)\n", filename, errno);
348  exit(1);
349  }
350  swapmemory(elf->scp[i_4]->data, "lllllllllls", 1);
351  break;
352  default:
353  elf->scp[i_4]->data = (uint8_t *)malloc(size);
354  if ( fread(elf->scp[i_4]->data, size, 1, fp) != 1 )
355  {
356  fprintf(stderr, "%s: Could not read ELF section contents (errno=%d)\n", filename, errno);
357  exit(1);
358  }
359  break;
360  }
361  }
362  }
363  }
364  fclose(fp);
365  return elf;
366 }
367 
368 static int is_in_range(unsigned int top, unsigned int size, unsigned int pos)
369 {
370  if ( pos >= top && pos < size + top )
371  {
372  return 1;
373  }
374  return 0;
375 }
376 
377 static void read_symtab(elf_file *elf, int sctindex, FILE *fp)
378 {
379  elf_syment **result;
380  elf_section *sp_x;
381  unsigned int entrise;
382  unsigned int i;
383 
384  sp_x = elf->scp[sctindex];
385  entrise = sp_x->shr.sh_size / sp_x->shr.sh_entsize;
386  result = (elf_syment **)calloc(entrise, sizeof(elf_syment *));
387  sp_x->data = (uint8_t *)result;
388  for ( i = 0; entrise > i; i += 1 )
389  {
390  result[i] = (elf_syment *)calloc(1, sizeof(elf_syment));
391  if ( fread(result[i], sp_x->shr.sh_entsize, 1, fp) != 1 )
392  {
393  fprintf(stderr, "elflib: Could not read ELF symbol table (errno=%d)\n", errno);
394  exit(1);
395  }
396  swapmemory(result[i], "lllccs", 1);
397  result[i]->bind = result[i]->sym.st_info >> 4;
398  result[i]->type = result[i]->sym.st_info & 0xF;
399  result[i]->name = 0;
400  if ( result[i]->sym.st_name )
401  {
402  result[i]->name = strdup((char *)&sp_x->link->data[result[i]->sym.st_name]);
403  }
404  if ( result[i]->sym.st_shndx && result[i]->sym.st_shndx <= 0xFEFF )
405  {
406  result[i]->shptr = elf->scp[result[i]->sym.st_shndx];
407  }
408  else
409  {
410  result[i]->shptr = 0;
411  }
412  }
413 }
414 
415 static void read_rel(elf_file *elf, int sctindex, FILE *fp)
416 {
417  elf_syment **symp;
418  elf_rel *result;
419  elf_section *sp_x;
420  unsigned int entrise;
421  unsigned int i;
422 
423  sp_x = elf->scp[sctindex];
424  entrise = sp_x->shr.sh_size / sp_x->shr.sh_entsize;
425  result = (elf_rel *)calloc(entrise, sizeof(elf_rel));
426  sp_x->data = (uint8_t *)result;
427  symp = (elf_syment **)sp_x->link->data;
428  for ( i = 0; entrise > i; i += 1 )
429  {
430  if ( fread(&result[i], sp_x->shr.sh_entsize, 1, fp) != 1 )
431  {
432  fprintf(stderr, "elflib: Could not read ELF relocations (errno=%d)\n", errno);
433  exit(1);
434  }
435  swapmemory(&result[i], "ll", 1);
436  result[i].type = result[i].rel.r_info & 0xFF;
437  // Workaround for malformed file: Handle case of missing .symtab/.strtab section
438  if ( symp )
439  {
440  result[i].symptr = symp[result[i].rel.r_info >> 8];
441  result[i].symptr->refcount += 1;
442  }
443  }
444 }
445 
446 static elf_mips_symbolic_data *read_mips_symbolic(FILE *fp)
447 {
449 
450  sycb = (elf_mips_symbolic_data *)malloc(sizeof(elf_mips_symbolic_data));
451  if ( fread(sycb, sizeof(hdrr), 1, fp) != 1 )
452  {
453  fprintf(stderr, "elflib: Could not read ELF debug info contents (errno=%d)\n", errno);
454  exit(1);
455  }
456  swapmemory(sycb, "sslllllllllllllllllllllll", 1);
457  if ( sycb->head.cbLineOffset > 0 )
458  {
459  size_t size_1;
460 
461  size_1 = sycb->head.cbLine;
462  sycb->cbLine_Ptr = (char *)malloc(size_1);
463  fseek(fp, sycb->head.cbLineOffset, SEEK_SET);
464  if ( fread(sycb->cbLine_Ptr, size_1, 1, fp) != 1 )
465  {
466  fprintf(stderr, "elflib: Could not read ELF debug info contents (errno=%d)\n", errno);
467  exit(1);
468  }
469  }
470  if ( sycb->head.cbDnOffset > 0 )
471  {
472  size_t size_2;
473 
474  size_2 = 8L * sycb->head.idnMax;
475  sycb->cbDn_Ptr = (char *)malloc(size_2);
476  fseek(fp, sycb->head.cbDnOffset, SEEK_SET);
477  if ( fread(sycb->cbDn_Ptr, size_2, 1, fp) != 1 )
478  {
479  fprintf(stderr, "elflib: Could not read ELF debug info contents (errno=%d)\n", errno);
480  exit(1);
481  }
482  swapmemory(sycb->cbDn_Ptr, "ll", sycb->head.idnMax);
483  }
484  if ( sycb->head.cbPdOffset > 0 )
485  {
486  size_t size_3;
487 
488  size_3 = 52L * sycb->head.ipdMax;
489  sycb->cbPd_Ptr = (char *)malloc(size_3);
490  fseek(fp, sycb->head.cbPdOffset, SEEK_SET);
491  if ( fread(sycb->cbPd_Ptr, size_3, 1, fp) != 1 )
492  {
493  fprintf(stderr, "elflib: Could not read ELF debug info contents (errno=%d)\n", errno);
494  exit(1);
495  }
496  swapmemory(sycb->cbPd_Ptr, "lllllllllsslll", sycb->head.ipdMax);
497  }
498  if ( sycb->head.cbSymOffset > 0 )
499  {
500  size_t size_4;
501 
502  size_4 = 12L * sycb->head.isymMax;
503  sycb->cbSym_Ptr = (char *)malloc(size_4);
504  fseek(fp, sycb->head.cbSymOffset, SEEK_SET);
505  if ( fread(sycb->cbSym_Ptr, size_4, 1, fp) != 1 )
506  {
507  fprintf(stderr, "elflib: Could not read ELF debug info contents (errno=%d)\n", errno);
508  exit(1);
509  }
510  swapmemory(sycb->cbSym_Ptr, "lll", sycb->head.isymMax);
511  }
512  if ( sycb->head.cbOptOffset > 0 )
513  {
514  size_t size_5;
515 
516  size_5 = 12L * sycb->head.ioptMax;
517  sycb->cbOpt_Ptr = (char *)malloc(size_5);
518  fseek(fp, sycb->head.cbOptOffset, SEEK_SET);
519  if ( fread(sycb->cbOpt_Ptr, size_5, 1, fp) != 1 )
520  {
521  fprintf(stderr, "elflib: Could not read ELF debug info contents (errno=%d)\n", errno);
522  exit(1);
523  }
524  swapmemory(sycb->cbOpt_Ptr, "lll", sycb->head.ioptMax);
525  }
526  if ( sycb->head.cbAuxOffset > 0 )
527  {
528  size_t size_6;
529 
530  size_6 = 4L * sycb->head.iauxMax;
531  sycb->cbAux_Ptr = (char *)malloc(size_6);
532  fseek(fp, sycb->head.cbAuxOffset, SEEK_SET);
533  if ( fread(sycb->cbAux_Ptr, size_6, 1, fp) != 1 )
534  {
535  fprintf(stderr, "elflib: Could not read ELF debug info contents (errno=%d)\n", errno);
536  exit(1);
537  }
538  swapmemory(sycb->cbAux_Ptr, "l", sycb->head.iauxMax);
539  }
540  if ( sycb->head.cbSsOffset > 0 )
541  {
542  size_t size_7;
543 
544  size_7 = sycb->head.issMax;
545  sycb->cbSs_Ptr = (char *)malloc(size_7);
546  fseek(fp, sycb->head.cbSsOffset, SEEK_SET);
547  if ( fread(sycb->cbSs_Ptr, size_7, 1, fp) != 1 )
548  {
549  fprintf(stderr, "elflib: Could not read ELF debug info contents (errno=%d)\n", errno);
550  exit(1);
551  }
552  }
553  if ( sycb->head.cbSsExtOffset > 0 )
554  {
555  size_t size_8;
556 
557  size_8 = sycb->head.issExtMax;
558  sycb->cbSsExt_Ptr = (char *)malloc(size_8);
559  fseek(fp, sycb->head.cbSsExtOffset, SEEK_SET);
560  if ( fread(sycb->cbSsExt_Ptr, size_8, 1, fp) != 1 )
561  {
562  fprintf(stderr, "elflib: Could not read ELF debug info contents (errno=%d)\n", errno);
563  exit(1);
564  }
565  }
566  if ( sycb->head.cbFdOffset > 0 )
567  {
568  size_t size_9;
569 
570  size_9 = 72L * sycb->head.ifdMax;
571  sycb->cbFd_Ptr = (char *)malloc(size_9);
572  fseek(fp, sycb->head.cbFdOffset, SEEK_SET);
573  if ( fread(sycb->cbFd_Ptr, size_9, 1, fp) != 1 )
574  {
575  fprintf(stderr, "elflib: Could not read ELF debug info contents (errno=%d)\n", errno);
576  exit(1);
577  }
578  swapmemory(sycb->cbFd_Ptr, "llllllllllsslllllll", sycb->head.ifdMax);
579  }
580  if ( sycb->head.cbRfdOffset > 0 )
581  {
582  size_t size_A;
583 
584  size_A = 4L * sycb->head.crfd;
585  sycb->cbRfd_Ptr = (char *)malloc(size_A);
586  fseek(fp, sycb->head.cbRfdOffset, SEEK_SET);
587  if ( fread(sycb->cbRfd_Ptr, size_A, 1, fp) != 1 )
588  {
589  fprintf(stderr, "elflib: Could not read ELF debug info contents (errno=%d)\n", errno);
590  exit(1);
591  }
592  swapmemory(sycb->cbRfd_Ptr, "l", sycb->head.crfd);
593  }
594  if ( sycb->head.cbExtOffset > 0 )
595  {
596  size_t size_B;
597 
598  size_B = 16L * sycb->head.iextMax;
599  sycb->cbExt_Ptr = (char *)malloc(size_B);
600  fseek(fp, sycb->head.cbExtOffset, SEEK_SET);
601  if ( fread(sycb->cbExt_Ptr, size_B, 1, fp) != 1 )
602  {
603  fprintf(stderr, "elflib: Could not read ELF debug info contents (errno=%d)\n", errno);
604  exit(1);
605  }
606  swapmemory(sycb->cbExt_Ptr, "sslll", sycb->head.iextMax);
607  }
608  return sycb;
609 }
610 
611 int layout_elf_file(elf_file *elf)
612 {
613  Elf_file_slot *order;
614 
615  reorder_symtab(elf);
616  rebuild_section_name_strings(elf);
617  rebuild_symbol_name_strings(elf);
618  order = build_file_order_list(elf);
619  shrink_file_order_list(order);
620  writeback_file_order_list(elf, order);
621  free(order);
622  return 0;
623 }
624 
625 int write_elf(elf_file *elf, const char *filename)
626 {
627  FILE *fp;
628 
629  fp = fopen(filename, "wb");
630  if ( !fp )
631  {
632  fprintf(stderr, "\"%s\" can't open (errno=%d)\n", filename, errno);
633  return 1;
634  }
635  renumber_symtab(elf);
636  if ( elf->ehp->e_shnum && elf->ehp->e_shentsize )
637  {
638  int i_1;
639  int i_2;
640 
641  for ( i_1 = 0; i_1 < elf->ehp->e_shnum; i_1 += 1 )
642  {
643  elf->scp[i_1]->number = i_1;
644  }
645  for ( i_2 = 0; i_2 < elf->ehp->e_shnum; i_2 += 1 )
646  {
647  switch ( elf->scp[i_2]->shr.sh_type )
648  {
649 #pragma GCC diagnostic push
650 #pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
651  case SHT_RELA:
652  case SHT_REL:
653  elf->scp[i_2]->shr.sh_info = elf->scp[i_2]->info->number;
654  case SHT_SYMTAB:
655  case SHT_HASH:
656  case SHT_DYNAMIC:
657  case SHT_DYNSYM:
658  elf->scp[i_2]->shr.sh_link = elf->scp[i_2]->link->number;
659  break;
660 #pragma GCC diagnostic pop
661  default:
662  break;
663  }
664  if ( elf->scp[i_2] == elf->shstrptr )
665  {
666  elf->ehp->e_shstrndx = elf->scp[i_2]->number;
667  }
668  }
669  }
670  swapmemory(elf->ehp, "ccccccccccccccccsslllllssssss", 1);
671  fwrite(elf->ehp, sizeof(Elf32_Ehdr), 1, fp);
672  swapmemory(elf->ehp, "ccccccccccccccccsslllllssssss", 1);
673  if ( elf->ehp->e_phnum && elf->ehp->e_phentsize )
674  {
675  int count_1;
676  int i_3;
677 
678  count_1 = elf->ehp->e_phnum;
679  fseek(fp, elf->ehp->e_phoff, SEEK_SET);
680  for ( i_3 = 0; count_1 > i_3; i_3 += 1 )
681  {
682  swapmemory(&elf->php[i_3], "llllllll", 1);
683  fwrite(&elf->php[i_3], sizeof(Elf32_Phdr), 1, fp);
684  swapmemory(&elf->php[i_3], "llllllll", 1);
685  }
686  }
687  if ( elf->ehp->e_shnum && elf->ehp->e_shentsize )
688  {
689  int count_2;
690  int i_4;
691  int i_5;
692 
693  count_2 = elf->ehp->e_shnum;
694  fseek(fp, elf->ehp->e_shoff, SEEK_SET);
695  for ( i_4 = 0; count_2 > i_4; i_4 += 1 )
696  {
697  swapmemory(elf->scp[i_4], "llllllllll", 1);
698  fwrite(elf->scp[i_4], sizeof(Elf32_Shdr), 1, fp);
699  swapmemory(elf->scp[i_4], "llllllllll", 1);
700  }
701  for ( i_5 = 0; count_2 > i_5; i_5 += 1 )
702  {
703  unsigned int size;
704  unsigned int pos;
705 
706  pos = elf->scp[i_5]->shr.sh_offset;
707  size = elf->scp[i_5]->shr.sh_size;
708  if ( pos != 0 && size != 0 )
709  {
710  fseek(fp, pos, SEEK_SET);
711  switch ( elf->scp[i_5]->shr.sh_type )
712  {
713  case SHT_PROGBITS:
714  case SHT_RELA:
715  case SHT_HASH:
716  case SHT_DYNAMIC:
717  case SHT_MIPS_REGINFO:
718  swapmemory(elf->scp[i_5]->data, "l", size >> 2);
719  fwrite(elf->scp[i_5]->data, size, 1, fp);
720  swapmemory(elf->scp[i_5]->data, "l", size >> 2);
721  break;
722  case SHT_SYMTAB:
723  case SHT_DYNSYM:
724  write_symtab(elf, i_5, fp);
725  break;
726  case SHT_NOBITS:
727  break;
728  case SHT_REL:
729  write_rel(elf, i_5, fp);
730  break;
731  case SHT_MIPS_DEBUG:
732  write_mips_symbolic((elf_mips_symbolic_data *)elf->scp[i_5]->data, pos, fp);
733  break;
734  case SHT_SCE_IOPMOD:
735  swapmemory(elf->scp[i_5]->data, "lllllls", 1);
736  fwrite(elf->scp[i_5]->data, size, 1, fp);
737  swapmemory(elf->scp[i_5]->data, "lllllls", 1);
738  break;
739  case SHT_SCE_EEMOD:
740  swapmemory(elf->scp[i_5]->data, "lllllllllls", 1);
741  fwrite(elf->scp[i_5]->data, size, 1, fp);
742  swapmemory(elf->scp[i_5]->data, "lllllllllls", 1);
743  break;
744  default:
745  fwrite(elf->scp[i_5]->data, size, 1, fp);
746  break;
747  }
748  }
749  }
750  }
751  fclose(fp);
752  return 0;
753 }
754 
755 static void renumber_a_symtab(elf_section *scp)
756 {
757  elf_syment **syp;
758  unsigned int entrise;
759  unsigned int i;
760 
761  entrise = scp->shr.sh_size / scp->shr.sh_entsize;
762  syp = (elf_syment **)scp->data;
763  for ( i = 0; entrise > i; i += 1 )
764  {
765  syp[i]->number = i;
766  }
767 }
768 
769 static void renumber_symtab(elf_file *elf)
770 {
771  int sc;
772 
773  for ( sc = 1; sc < elf->ehp->e_shnum; sc += 1 )
774  {
775  switch ( elf->scp[sc]->shr.sh_type )
776  {
777  case SHT_SYMTAB:
778  case SHT_DYNSYM:
779  renumber_a_symtab(elf->scp[sc]);
780  break;
781  default:
782  break;
783  }
784  }
785 }
786 
787 static void write_symtab(elf_file *elf, int sctindex, FILE *fp)
788 {
789  Elf32_Sym sym;
790  elf_syment **syp;
791  elf_section *sp_x;
792  unsigned int entrise;
793  unsigned int i;
794 
795  sp_x = elf->scp[sctindex];
796  entrise = sp_x->shr.sh_size / sp_x->shr.sh_entsize;
797  syp = (elf_syment **)sp_x->data;
798  fseek(fp, sp_x->shr.sh_offset, SEEK_SET);
799  for ( i = 0; entrise > i; i += 1 )
800  {
801  memcpy(&sym, syp[i], sizeof(sym));
802  if ( syp[i]->shptr )
803  {
804  sym.st_shndx = syp[i]->shptr->number;
805  }
806  swapmemory(&sym, "lllccs", 1);
807  fwrite(&sym, sizeof(Elf32_Sym), 1, fp);
808  }
809 }
810 
811 static void write_rel(elf_file *elf, int sctindex, FILE *fp)
812 {
813  Elf32_Rel rel;
814  elf_rel *rp;
815  elf_section *sp_x;
816  unsigned int entrise;
817  unsigned int i;
818 
819  sp_x = elf->scp[sctindex];
820  entrise = sp_x->shr.sh_size / sp_x->shr.sh_entsize;
821  rp = (elf_rel *)sp_x->data;
822  fseek(fp, sp_x->shr.sh_offset, SEEK_SET);
823  for ( i = 0; entrise > i; i += 1 )
824  {
825  memcpy(&rel, &rp[i], sizeof(rel));
826  if ( rp[i].symptr && rp[i].symptr->number == (unsigned int)(-1) )
827  {
828  fprintf(stderr, "Internal error !!\n");
829  fprintf(stderr, " relocation entry have no symbol\nabort\n");
830  exit(1);
831  }
832  rel.r_info = ((rp[i].symptr ? rp[i].symptr->number : sp_x->info->number) << 8) + (rp[i].type & 0xFF);
833  swapmemory(&rel, "ll", 1);
834  fwrite(&rel, sizeof(Elf32_Rel), 1, fp);
835  }
836 }
837 
838 static void write_mips_symbolic(elf_mips_symbolic_data *sycb, unsigned int basepos, FILE *fp)
839 {
840  unsigned int pos;
841 
842  pos = basepos + 96;
843  if ( sycb->head.cbLineOffset > 0 )
844  {
845  size_t size_1;
846 
847  size_1 = sycb->head.cbLine;
848  sycb->head.cbLineOffset = pos;
849  pos += size_1;
850  fseek(fp, sycb->head.cbLineOffset, SEEK_SET);
851  fwrite(sycb->cbLine_Ptr, size_1, 1, fp);
852  }
853  if ( sycb->head.cbDnOffset > 0 )
854  {
855  size_t size_2;
856 
857  size_2 = 8L * sycb->head.idnMax;
858  sycb->head.cbDnOffset = pos;
859  pos += size_2;
860  fseek(fp, sycb->head.cbDnOffset, SEEK_SET);
861  swapmemory(sycb->cbDn_Ptr, "ll", sycb->head.idnMax);
862  fwrite(sycb->cbDn_Ptr, size_2, 1, fp);
863  swapmemory(sycb->cbDn_Ptr, "ll", sycb->head.idnMax);
864  }
865  if ( sycb->head.cbPdOffset > 0 )
866  {
867  size_t size_3;
868 
869  size_3 = 52L * sycb->head.ipdMax;
870  sycb->head.cbPdOffset = pos;
871  pos += size_3;
872  fseek(fp, sycb->head.cbPdOffset, SEEK_SET);
873  swapmemory(sycb->cbPd_Ptr, "lllllllllsslll", sycb->head.ipdMax);
874  fwrite(sycb->cbPd_Ptr, size_3, 1, fp);
875  swapmemory(sycb->cbPd_Ptr, "lllllllllsslll", sycb->head.ipdMax);
876  }
877  if ( sycb->head.cbSymOffset > 0 )
878  {
879  size_t size_4;
880 
881  size_4 = 12L * sycb->head.isymMax;
882  sycb->head.cbSymOffset = pos;
883  pos += size_4;
884  fseek(fp, sycb->head.cbSymOffset, SEEK_SET);
885  swapmemory(sycb->cbSym_Ptr, "lll", sycb->head.isymMax);
886  fwrite(sycb->cbSym_Ptr, size_4, 1, fp);
887  swapmemory(sycb->cbSym_Ptr, "lll", sycb->head.isymMax);
888  }
889  if ( sycb->head.cbOptOffset > 0 )
890  {
891  size_t size_5;
892 
893  size_5 = 12L * sycb->head.ioptMax;
894  pos += size_5;
895  fseek(fp, sycb->head.cbOptOffset, SEEK_SET);
896  swapmemory(sycb->cbOpt_Ptr, "lll", sycb->head.ioptMax);
897  fwrite(sycb->cbOpt_Ptr, size_5, 1, fp);
898  swapmemory(sycb->cbOpt_Ptr, "lll", sycb->head.ioptMax);
899  }
900  if ( sycb->head.cbAuxOffset > 0 )
901  {
902  size_t size_6;
903 
904  size_6 = 4L * sycb->head.iauxMax;
905  sycb->head.cbAuxOffset = pos;
906  pos += size_6;
907  fseek(fp, sycb->head.cbAuxOffset, SEEK_SET);
908  swapmemory(sycb->cbAux_Ptr, "l", sycb->head.iauxMax);
909  fwrite(sycb->cbAux_Ptr, size_6, 1, fp);
910  swapmemory(sycb->cbAux_Ptr, "l", sycb->head.iauxMax);
911  }
912  if ( sycb->head.cbSsOffset > 0 )
913  {
914  size_t size_7;
915 
916  size_7 = sycb->head.issMax;
917  sycb->head.cbSsOffset = pos;
918  pos += size_7;
919  fseek(fp, sycb->head.cbSsOffset, SEEK_SET);
920  fwrite(sycb->cbSs_Ptr, size_7, 1, fp);
921  }
922  if ( sycb->head.cbSsExtOffset > 0 )
923  {
924  size_t size_8;
925 
926  size_8 = sycb->head.issExtMax;
927  sycb->head.cbSsExtOffset = pos;
928  pos += size_8;
929  fseek(fp, sycb->head.cbSsExtOffset, SEEK_SET);
930  fwrite(sycb->cbSsExt_Ptr, size_8, 1, fp);
931  }
932  if ( sycb->head.cbFdOffset > 0 )
933  {
934  size_t size_9;
935 
936  size_9 = 72L * sycb->head.ifdMax;
937  sycb->head.cbFdOffset = pos;
938  pos += size_9;
939  fseek(fp, sycb->head.cbFdOffset, SEEK_SET);
940  swapmemory(sycb->cbFd_Ptr, "llllllllllsslllllll", sycb->head.ifdMax);
941  fwrite(sycb->cbFd_Ptr, size_9, 1, fp);
942  swapmemory(sycb->cbFd_Ptr, "llllllllllsslllllll", sycb->head.ifdMax);
943  }
944  if ( sycb->head.cbRfdOffset > 0 )
945  {
946  size_t size_A;
947 
948  size_A = 4L * sycb->head.crfd;
949  sycb->head.cbRfdOffset = pos;
950  pos += size_A;
951  fseek(fp, sycb->head.cbRfdOffset, SEEK_SET);
952  swapmemory(sycb->cbRfd_Ptr, "l", sycb->head.crfd);
953  fwrite(sycb->cbRfd_Ptr, size_A, 1, fp);
954  swapmemory(sycb->cbRfd_Ptr, "l", sycb->head.crfd);
955  }
956  if ( sycb->head.cbExtOffset > 0 )
957  {
958  size_t size_B;
959 
960  size_B = 16L * sycb->head.iextMax;
961  sycb->head.cbExtOffset = pos;
962  fseek(fp, sycb->head.cbExtOffset, SEEK_SET);
963  swapmemory(sycb->cbExt_Ptr, "sslll", sycb->head.iextMax);
964  fwrite(sycb->cbExt_Ptr, size_B, 1, fp);
965  swapmemory(sycb->cbExt_Ptr, "sslll", sycb->head.iextMax);
966  }
967  fseek(fp, basepos, SEEK_SET);
968  swapmemory(sycb, "sslllllllllllllllllllllll", 1);
969  fwrite(sycb, sizeof(hdrr), 1, fp);
970  swapmemory(sycb, "sslllllllllllllllllllllll", 1);
971 }
972 
973 void add_section(elf_file *elf, elf_section *scp)
974 {
975  Elf32_Ehdr *ehp;
976  int count;
977 
978  ehp = elf->ehp;
979  ehp->e_shnum += 1;
980  count = ehp->e_shnum;
981  elf->scp = (elf_section **)realloc(elf->scp, (count + 1) * sizeof(elf_section *));
982  elf->scp[count - 1] = scp;
983  elf->scp[count] = 0;
984  add_symbol(elf, 0, 0, 3, 0, scp, 0);
985 }
986 
987 elf_section *remove_section(elf_file *elf, Elf32_Word shtype)
988 {
989  elf_section *rmsec;
990  int s;
991 
992  rmsec = 0;
993  for ( s = 1; s < elf->ehp->e_shnum; s += 1 )
994  {
995  if ( shtype == elf->scp[s]->shr.sh_type )
996  {
997  elf->ehp->e_shnum -= 1;
998  rmsec = elf->scp[s];
999  break;
1000  }
1001  }
1002  for ( ; s < elf->ehp->e_shnum; s += 1 )
1003  {
1004  elf->scp[s] = elf->scp[s + 1];
1005  }
1006  return rmsec;
1007 }
1008 
1009 elf_section *remove_section_by_name(elf_file *elf, const char *secname)
1010 {
1011  elf_section *rmsec;
1012  int s;
1013 
1014  rmsec = 0;
1015  for ( s = 1; s < elf->ehp->e_shnum; s += 1 )
1016  {
1017  if ( !strcmp(elf->scp[s]->name, secname) )
1018  {
1019  elf->ehp->e_shnum -= 1;
1020  rmsec = elf->scp[s];
1021  break;
1022  }
1023  }
1024  for ( ; s < elf->ehp->e_shnum; s += 1 )
1025  {
1026  elf->scp[s] = elf->scp[s + 1];
1027  }
1028  return rmsec;
1029 }
1030 
1031 elf_section *search_section(elf_file *elf, Elf32_Word stype)
1032 {
1033  int i;
1034 
1035  for ( i = 1; i < elf->ehp->e_shnum; i += 1 )
1036  {
1037  if ( stype == elf->scp[i]->shr.sh_type )
1038  {
1039  return elf->scp[i];
1040  }
1041  }
1042  return 0;
1043 }
1044 
1045 elf_section *search_section_by_name(elf_file *elf, const char *secname)
1046 {
1047  int i;
1048 
1049  for ( i = 1; i < elf->ehp->e_shnum; i += 1 )
1050  {
1051  if ( !strcmp(elf->scp[i]->name, secname) )
1052  {
1053  return elf->scp[i];
1054  }
1055  }
1056  return 0;
1057 }
1058 
1059 unsigned int *get_section_data(elf_file *elf, unsigned int addr)
1060 {
1061  int i;
1062 
1063  for ( i = 1; i < elf->ehp->e_shnum; i += 1 )
1064  {
1065  if (
1066  elf->scp[i]->shr.sh_type == SHT_PROGBITS && addr >= elf->scp[i]->shr.sh_addr
1067  && addr < elf->scp[i]->shr.sh_size + elf->scp[i]->shr.sh_addr )
1068  {
1069  return (unsigned int *)&elf->scp[i]->data[addr - elf->scp[i]->shr.sh_addr];
1070  }
1071  }
1072  return 0;
1073 }
1074 
1075 elf_syment *search_global_symbol(const char *name, elf_file *elf)
1076 {
1077  unsigned int entrise;
1078  unsigned int i;
1079  elf_syment **syp;
1080  elf_section *scp;
1081 
1082  scp = search_section(elf, SHT_SYMTAB);
1083  if ( !scp )
1084  {
1085  return 0;
1086  }
1087  entrise = scp->shr.sh_size / scp->shr.sh_entsize;
1088  syp = (elf_syment **)scp->data;
1089  for ( i = 1; entrise > i; i += 1 )
1090  {
1091  if ( syp[i]->name && syp[i]->bind == STB_GLOBAL && !strcmp(syp[i]->name, name) )
1092  {
1093  return syp[i];
1094  }
1095  }
1096  return 0;
1097 }
1098 
1099 int is_defined_symbol(const elf_syment *sym)
1100 {
1101  if ( !sym )
1102  {
1103  return 0;
1104  }
1105  if ( !sym->sym.st_shndx )
1106  {
1107  return 0;
1108  }
1109  if ( sym->sym.st_shndx <= 0xFEFF )
1110  {
1111  return 1;
1112  }
1113  return sym->sym.st_shndx == SHN_ABS;
1114 }
1115 
1116 elf_syment *add_symbol(elf_file *elf, const char *name, int bind, int type, int value, elf_section *scp, int st_shndx)
1117 {
1118  unsigned int entrise;
1119  elf_syment *sym;
1120  elf_syment **newtab;
1121  elf_section *symtbl;
1122 
1123  symtbl = search_section(elf, SHT_SYMTAB);
1124  if ( !symtbl )
1125  {
1126  return 0;
1127  }
1128  entrise = symtbl->shr.sh_size / symtbl->shr.sh_entsize;
1129  newtab = (elf_syment **)realloc(symtbl->data, (entrise + 1) * sizeof(elf_syment *));
1130  sym = (elf_syment *)calloc(1, sizeof(elf_syment));
1131  newtab[entrise] = sym;
1132  symtbl->shr.sh_size += symtbl->shr.sh_entsize;
1133  symtbl->data = (uint8_t *)newtab;
1134  if ( name )
1135  {
1136  sym->name = strdup(name);
1137  }
1138  sym->bind = bind;
1139  sym->type = type;
1140  sym->sym.st_info = (type & 0xF) + 16 * bind;
1141  sym->sym.st_value = value;
1142  sym->shptr = scp;
1143  if ( scp )
1144  {
1145  sym->sym.st_shndx = 1;
1146  }
1147  else
1148  {
1149  sym->sym.st_shndx = st_shndx;
1150  }
1151  return sym;
1152 }
1153 
1154 unsigned int get_symbol_value(const elf_syment *sym, const elf_file *elf)
1155 {
1156  if ( !is_defined_symbol(sym) )
1157  {
1158  return 0;
1159  }
1160  if ( sym->sym.st_shndx != SHN_ABS && elf->ehp->e_type == ET_REL )
1161  {
1162  return sym->shptr->shr.sh_addr + sym->sym.st_value;
1163  }
1164  return sym->sym.st_value;
1165 }
1166 
1167 static void reorder_an_symtab(elf_file *elf, elf_section *scp)
1168 {
1169  int sections;
1170  elf_syment **oldtab;
1171  elf_syment **newtab;
1172  unsigned int entrise;
1173  int sc;
1174  unsigned int d;
1175  unsigned int i;
1176  unsigned int j;
1177  unsigned int k;
1178  unsigned int m;
1179 
1180  sections = elf->ehp->e_shnum;
1181  entrise = scp->shr.sh_size / scp->shr.sh_entsize;
1182  oldtab = (elf_syment **)malloc(entrise * sizeof(elf_syment *));
1183  memcpy(oldtab, (elf_syment **)scp->data, entrise * sizeof(elf_syment *));
1184  newtab = (elf_syment **)calloc(entrise, sizeof(elf_syment *));
1185  scp->data = (uint8_t *)newtab;
1186  *newtab = *oldtab;
1187  d = 1;
1188  for ( sc = 1; sections > sc; sc += 1 )
1189  {
1190  for ( i = 1; entrise > i; i += 1 )
1191  {
1192  if (
1193  oldtab[i] && oldtab[i]->type == STT_SECTION && !oldtab[i]->name && oldtab[i]->shptr
1194  && !strcmp(oldtab[i]->shptr->name, elf->scp[sc]->name) )
1195  {
1196  newtab[d] = oldtab[i];
1197  d += 1;
1198  oldtab[i] = 0;
1199  break;
1200  }
1201  }
1202  }
1203  for ( j = 1; entrise > j; j += 1 )
1204  {
1205  if ( oldtab[j] && oldtab[j]->type == STT_SECTION && !oldtab[j]->name )
1206  {
1207  oldtab[j] = 0;
1208  }
1209  }
1210  for ( k = 1; entrise > k; k += 1 )
1211  {
1212  if ( oldtab[k] && !oldtab[k]->bind )
1213  {
1214  newtab[d] = oldtab[k];
1215  d += 1;
1216  oldtab[k] = 0;
1217  }
1218  }
1219  scp->shr.sh_info = d;
1220  for ( m = 1; entrise > m; m += 1 )
1221  {
1222  if ( oldtab[m] )
1223  {
1224  newtab[d] = oldtab[m];
1225  d += 1;
1226  oldtab[m] = 0;
1227  }
1228  }
1229  scp->shr.sh_size = scp->shr.sh_entsize * d;
1230  free(oldtab);
1231 }
1232 
1233 void reorder_symtab(elf_file *elf)
1234 {
1235  int s;
1236 
1237  for ( s = 1; s < elf->ehp->e_shnum; s += 1 )
1238  {
1239  switch ( elf->scp[s]->shr.sh_type )
1240  {
1241  case SHT_SYMTAB:
1242  case SHT_DYNSYM:
1243  reorder_an_symtab(elf, elf->scp[s]);
1244  break;
1245  default:
1246  break;
1247  }
1248  }
1249 }
1250 
1251 unsigned int adjust_align(unsigned int value, unsigned int align)
1252 {
1253  return ~(align - 1) & (align + value - 1);
1254 }
1255 
1256 void rebuild_section_name_strings(elf_file *elf)
1257 {
1258  unsigned int offset;
1259  size_t namesize;
1260  int i_1;
1261  int i_2;
1262 
1263  namesize = 1;
1264  if ( elf->scp == NULL )
1265  {
1266  return;
1267  }
1268  for ( i_1 = 1; i_1 < elf->ehp->e_shnum; i_1 += 1 )
1269  {
1270  namesize += strlen(elf->scp[i_1]->name) + 1;
1271  }
1272  if ( elf->shstrptr->data )
1273  {
1274  free(elf->shstrptr->data);
1275  }
1276  elf->shstrptr->data = (uint8_t *)calloc(1, namesize);
1277  elf->shstrptr->shr.sh_size = namesize;
1278  offset = 1;
1279  for ( i_2 = 1; i_2 < elf->ehp->e_shnum; i_2 += 1 )
1280  {
1281  strcpy((char *)&elf->shstrptr->data[offset], elf->scp[i_2]->name);
1282  elf->scp[i_2]->shr.sh_name = offset;
1283  offset += strlen(elf->scp[i_2]->name) + 1;
1284  }
1285 }
1286 
1287 static size_t search_string_table(const char *tbltop, size_t endindex, const char *str)
1288 {
1289  size_t idx;
1290 
1291  for ( idx = 1; idx < endindex; idx += strlen(&tbltop[idx]) + 1 )
1292  {
1293  if ( !strcmp(str, &tbltop[idx]) )
1294  {
1295  return idx;
1296  }
1297  }
1298  return 0;
1299 }
1300 
1301 static void rebuild_a_symbol_name_strings(elf_section *scp)
1302 {
1303  elf_section *strtab;
1304  elf_syment **syp;
1305  size_t offset;
1306  size_t namesize;
1307  unsigned int entrise;
1308  unsigned int i_1;
1309  unsigned int i_2;
1310 
1311  entrise = scp->shr.sh_size / scp->shr.sh_entsize;
1312  strtab = scp->link;
1313  syp = (elf_syment **)scp->data;
1314  namesize = 1;
1315  for ( i_1 = 1; i_1 < entrise; i_1 += 1 )
1316  {
1317  namesize = (syp[i_1] != NULL && syp[i_1]->name != NULL) ? (strlen(syp[i_1]->name) + namesize + 1) : namesize;
1318  }
1319  if ( strtab->data )
1320  {
1321  free(strtab->data);
1322  }
1323  strtab->data = (uint8_t *)calloc(1, namesize);
1324  offset = 1;
1325  for ( i_2 = 1; i_2 < entrise; i_2 += 1 )
1326  {
1327  if ( syp[i_2] != NULL && syp[i_2]->name != NULL )
1328  {
1329  syp[i_2]->sym.st_name = search_string_table((char *)strtab->data, offset, syp[i_2]->name);
1330  if ( !syp[i_2]->sym.st_name )
1331  {
1332  strcpy((char *)&strtab->data[offset], syp[i_2]->name);
1333  syp[i_2]->sym.st_name = offset;
1334  offset += strlen(syp[i_2]->name) + 1;
1335  }
1336  }
1337  }
1338  strtab->shr.sh_size = offset;
1339 }
1340 
1341 void rebuild_symbol_name_strings(elf_file *elf)
1342 {
1343  int sc;
1344 
1345  if ( elf->scp == NULL )
1346  {
1347  return;
1348  }
1349  for ( sc = 1; sc < elf->ehp->e_shnum; sc += 1 )
1350  {
1351  switch ( elf->scp[sc]->shr.sh_type )
1352  {
1353  case SHT_SYMTAB:
1354  case SHT_DYNSYM:
1355  rebuild_a_symbol_name_strings(elf->scp[sc]);
1356  break;
1357  default:
1358  break;
1359  }
1360  }
1361 }
1362 
1363 static int comp_Elf_file_slot(const void *a1, const void *a2)
1364 {
1365  const Elf_file_slot *p1;
1366  const Elf_file_slot *p2;
1367 
1368  p1 = a1;
1369  p2 = a2;
1370 
1371  if ( p1->type == EFS_TYPE_ELF_HEADER && p2->type == EFS_TYPE_ELF_HEADER )
1372  {
1373  return 0;
1374  }
1375  if ( p1->type == EFS_TYPE_ELF_HEADER )
1376  {
1377  return -1;
1378  }
1379  if ( p2->type == EFS_TYPE_ELF_HEADER )
1380  {
1381  return 1;
1382  }
1383  if ( p1->type == EFS_TYPE_PROGRAM_HEADER_TABLE && p2->type == EFS_TYPE_PROGRAM_HEADER_TABLE )
1384  {
1385  return 0;
1386  }
1387  if ( p1->type == EFS_TYPE_PROGRAM_HEADER_TABLE )
1388  {
1389  return -1;
1390  }
1391  if ( p2->type == EFS_TYPE_PROGRAM_HEADER_TABLE )
1392  {
1393  return 1;
1394  }
1395  if ( !p1->type && !p2->type )
1396  {
1397  return 0;
1398  }
1399  if ( !p1->type )
1400  {
1401  return 1;
1402  }
1403  if ( !p2->type )
1404  {
1405  return -1;
1406  }
1407  if ( p1->type == EFS_TYPE_END && p2->type == EFS_TYPE_END )
1408  {
1409  return 0;
1410  }
1411  if ( p1->type == EFS_TYPE_END )
1412  {
1413  return 1;
1414  }
1415  if ( p2->type == EFS_TYPE_END )
1416  {
1417  return -1;
1418  }
1419  if ( p1->type == EFS_TYPE_PROGRAM_HEADER_ENTRY && p2->type == EFS_TYPE_SECTION_HEADER_TABLE )
1420  {
1421  return -1;
1422  }
1423  if ( p1->type == EFS_TYPE_SECTION_HEADER_TABLE && p2->type == EFS_TYPE_PROGRAM_HEADER_ENTRY )
1424  {
1425  return 1;
1426  }
1427  if ( p2->offset == p1->offset )
1428  {
1429  return 0;
1430  }
1431  if ( p2->offset >= p1->offset )
1432  {
1433  return -1;
1434  }
1435  return 1;
1436 }
1437 
1438 Elf_file_slot *build_file_order_list(const elf_file *elf)
1439 {
1440  int sections;
1441  elf_section **scp;
1442  Elf_file_slot *resolt;
1443  int s_2;
1444  int d_1;
1445  size_t d_2;
1446  int maxent;
1447 
1448  sections = elf->ehp->e_shnum;
1449  scp = (elf_section **)calloc(sections + 1, sizeof(elf_section *));
1450  memcpy(scp, elf->scp, sections * sizeof(elf_section *));
1451  maxent = elf->ehp->e_shnum + 2;
1452  if ( elf->ehp->e_phnum )
1453  {
1454  maxent = elf->ehp->e_phnum + elf->ehp->e_shnum + 3;
1455  }
1456  resolt = (Elf_file_slot *)calloc(maxent, sizeof(Elf_file_slot));
1457  resolt->type = EFS_TYPE_ELF_HEADER;
1458  resolt->offset = 0;
1459  resolt->size = sizeof(Elf32_Ehdr);
1460  resolt->align = 4;
1461  d_1 = 1;
1462  if ( elf->ehp->e_phnum )
1463  {
1464  int seg;
1465 
1466  resolt[1].type = EFS_TYPE_PROGRAM_HEADER_TABLE;
1467  resolt[1].offset = resolt->size;
1468  resolt[1].size = sizeof(Elf32_Phdr) * elf->ehp->e_phnum;
1469  resolt[1].align = 4;
1470  for ( seg = 0, d_1 = 2; seg < elf->ehp->e_phnum; seg += 1, d_1 += 1 )
1471  {
1472  elf_section **phdscp;
1473 
1474  resolt[d_1].type = EFS_TYPE_PROGRAM_HEADER_ENTRY;
1475  resolt[d_1].d.php = &elf->php[seg];
1476  resolt[d_1].offset = elf->php[seg].phdr.p_offset;
1477  resolt[d_1].size = elf->php[seg].phdr.p_filesz;
1478  resolt[d_1].align = elf->php[seg].phdr.p_align;
1479  for ( phdscp = elf->php[seg].scp; *phdscp; phdscp += 1 )
1480  {
1481  int s_1;
1482 
1483  for ( s_1 = 0; s_1 < sections; s_1 += 1 )
1484  {
1485  if ( *phdscp == scp[s_1] )
1486  {
1487  scp[s_1] = 0;
1488  break;
1489  }
1490  }
1491  }
1492  }
1493  }
1494  resolt[d_1].type = EFS_TYPE_SECTION_HEADER_TABLE;
1495  resolt[d_1].offset = elf->ehp->e_shoff ?: (Elf32_Off)(-256);
1496  resolt[d_1].size = sizeof(Elf32_Shdr) * elf->ehp->e_shnum;
1497  resolt[d_1].align = 4;
1498  d_2 = d_1 + 1;
1499  for ( s_2 = 1; s_2 < sections; s_2 += 1 )
1500  {
1501  if ( scp[s_2] )
1502  {
1503  resolt[d_2].type = EFS_TYPE_SECTION_DATA;
1504  resolt[d_2].d.scp = scp[s_2];
1505  resolt[d_2].offset = scp[s_2]->shr.sh_offset;
1506  resolt[d_2].size = scp[s_2]->shr.sh_size;
1507  resolt[d_2].align = scp[s_2]->shr.sh_addralign;
1508  scp[s_2] = 0;
1509  d_2 += 1;
1510  }
1511  }
1512  resolt[d_2].type = EFS_TYPE_END;
1513  free(scp);
1514  qsort(resolt, d_2, sizeof(Elf_file_slot), comp_Elf_file_slot);
1515  return resolt;
1516 }
1517 
1518 void shrink_file_order_list(Elf_file_slot *efs)
1519 {
1520  unsigned int slot;
1521 
1522  slot = 0;
1523  for ( ; efs->type != EFS_TYPE_END; efs += 1 )
1524  {
1525  unsigned int foffset;
1526 
1527  foffset = adjust_align(slot, efs->align);
1528  efs->offset = foffset;
1529  slot = efs->size + foffset;
1530  }
1531 }
1532 
1533 void writeback_file_order_list(elf_file *elf, Elf_file_slot *efs)
1534 {
1535  elf_section **scp;
1536  unsigned int segoffset;
1537  int i;
1538 
1539  for ( ; efs->type != EFS_TYPE_END; efs += 1 )
1540  {
1541  switch ( efs->type )
1542  {
1543  case EFS_TYPE_PROGRAM_HEADER_TABLE:
1544  elf->ehp->e_phoff = efs->offset;
1545  break;
1546  case EFS_TYPE_PROGRAM_HEADER_ENTRY:
1547  efs->d.php->phdr.p_offset = efs->offset;
1548  scp = efs->d.php->scp;
1549  segoffset = efs->offset;
1550  (*scp)->shr.sh_offset = efs->offset;
1551  for ( i = 1; scp[i]; i += 1 )
1552  {
1553  if ( scp[i]->shr.sh_type != SHT_NOBITS )
1554  {
1555  segoffset = scp[i]->shr.sh_addr + efs->offset - (*scp)->shr.sh_addr;
1556  }
1557  scp[i]->shr.sh_offset = segoffset;
1558  if ( scp[i]->shr.sh_type != SHT_NOBITS )
1559  {
1560  segoffset += scp[i]->shr.sh_size;
1561  }
1562  }
1563  break;
1564  case EFS_TYPE_SECTION_HEADER_TABLE:
1565  elf->ehp->e_shoff = efs->offset;
1566  break;
1567  case EFS_TYPE_SECTION_DATA:
1568  efs->d.php->phdr.p_filesz = efs->offset;
1569  break;
1570  default:
1571  break;
1572  }
1573  }
1574 }
1575 
1576 void dump_file_order_list(const elf_file *elf, const Elf_file_slot *efs)
1577 {
1578  unsigned int offset;
1579  unsigned int size_tmp;
1580  unsigned int offset_tmp;
1581  char tmp[100];
1582  const char *name;
1583  elf_section **scp;
1584  const Elf_file_slot *slot;
1585  int i;
1586 
1587  offset_tmp = efs->offset;
1588  printf("\n");
1589  for ( slot = efs; slot->type != EFS_TYPE_END; slot += 1 )
1590  {
1591  unsigned int oldend_1;
1592  unsigned int size_1;
1593  unsigned int startpos_1;
1594 
1595  oldend_1 = slot->size;
1596  startpos_1 = slot->offset;
1597  if ( oldend_1 == 0 )
1598  {
1599  offset = slot->offset;
1600  }
1601  else
1602  {
1603  offset = oldend_1 + startpos_1 - 1;
1604  }
1605  size_1 = offset;
1606  switch ( slot->type )
1607  {
1608  case EFS_TYPE_ELF_HEADER:
1609  name = "[Elf header]";
1610  break;
1611  case EFS_TYPE_PROGRAM_HEADER_TABLE:
1612  name = "[Proram Header Table]";
1613  break;
1614  case EFS_TYPE_PROGRAM_HEADER_ENTRY:
1615  snprintf(tmp, sizeof(tmp), "[Proram Header entry %d]", (int)(0xCCCCCCCD * ((char *)slot->d.php - (char *)elf->php)) >> 3);
1616  name = tmp;
1617  break;
1618  case EFS_TYPE_SECTION_HEADER_TABLE:
1619  name = "[Section Header Table]";
1620  break;
1621  case EFS_TYPE_SECTION_DATA:
1622  snprintf(tmp, sizeof(tmp), "%s data", slot->d.scp->name);
1623  name = tmp;
1624  break;
1625  default:
1626  name = "internal error Unknown EFS type !!!!";
1627  break;
1628  }
1629  if ( startpos_1 > offset_tmp + 1 )
1630  {
1631  printf("%36s = %08x-%08x (%06x)\n", "**Blank**", offset_tmp + 1, startpos_1 - 1, startpos_1 - offset_tmp - 1);
1632  }
1633  offset_tmp = size_1;
1634  printf("%36s = %08x-%08x (%06x)\n", name, startpos_1, size_1, oldend_1);
1635  if ( slot->type == EFS_TYPE_PROGRAM_HEADER_ENTRY )
1636  {
1637  scp = slot->d.php->scp;
1638  (*scp)->shr.sh_offset = slot->offset;
1639  size_tmp = slot->offset;
1640  for ( i = 0; scp[i]; i += 1 )
1641  {
1642  unsigned int oldend_2;
1643  unsigned int size_2;
1644  unsigned int startpos_2;
1645 
1646  if ( scp[i]->shr.sh_type == SHT_NOBITS )
1647  {
1648  oldend_2 = 0;
1649  }
1650  else
1651  {
1652  oldend_2 = scp[i]->shr.sh_size;
1653  }
1654  startpos_2 = scp[i]->shr.sh_offset;
1655  size_2 = (oldend_2 == 0) ? (scp[i]->shr.sh_offset) : (Elf32_Off)(oldend_2 + startpos_2 - 1);
1656  snprintf(tmp, sizeof(tmp), "(%s)", scp[i]->name);
1657  name = tmp;
1658  if ( startpos_2 > size_tmp + 1 )
1659  {
1660  printf("%36s | %08x-%08x (%06x)\n", "**Blank**", size_tmp + 1, startpos_2 - 1, startpos_2 - size_tmp - 1);
1661  }
1662  size_tmp = size_2;
1663  printf("%36s | %08x-%08x (%06x)\n", name, startpos_2, size_2, scp[i]->shr.sh_size);
1664  }
1665  }
1666  }
1667 }
_Elf32_ehdr
Definition: srxfixup_internal.h:25
_Elf32_Shdr
Definition: srxfixup_internal.h:53
Elf32_Rel
Definition: elftypes.h:221
elf_rel
Definition: loadcore.c:71
_elffile
Definition: srxfixup_internal.h:285
_elf_section
Definition: srxfixup_internal.h:253
count
u32 count
start sector of fragmented bd/file
Definition: usbhdfsd-common.h:3
Elf32_Phdr
Definition: elftypes.h:207
_elf_mips_symbolic
Definition: srxfixup_internal.h:238
_Elf32_Sym
Definition: srxfixup_internal.h:66
_elf_proghead
Definition: srxfixup_internal.h:279
stdio.h
_hdrr
Definition: srxfixup_internal.h:119
_elf_file_slot
Definition: srxfixup_internal.h:296
stdlib.h
_syment
Definition: srxfixup_internal.h:263
errno.h