CHDK_DE Vorschauversion  Trunk Rev. 6014
 Alle Datenstrukturen Dateien Funktionen Variablen Typdefinitionen Aufzählungen Aufzählungswerte Makrodefinitionen
elf-arm.c-Dateireferenz
#include <stdlib.h>
#include <string.h>
#include "myio.h"
#include "elfflt.h"
+ Include-Abhängigkeitsdiagramm für elf-arm.c:

gehe zum Quellcode dieser Datei

Funktionen

int apply_realloc (struct relevant_section *base_sect, struct elf32_rela *rela, struct relevant_section *tgt_sect, struct elf32_sym *sym, int i)
 
int apply_import (struct relevant_section *base_sect, struct elf32_rela *rela, int importidx, struct elf32_sym *sym)
 

Variablen

uint32_t offs_divsi3_skip_div0_test
 
uint32_t offs_div0_from_arm
 
uint32_t offs__aeabi_uidiv
 

Dokumentation der Funktionen

int apply_import ( struct relevant_section base_sect,
struct elf32_rela rela,
int  importidx,
struct elf32_sym sym 
)

Definiert in Zeile 214 der Datei elf-arm.c.

219 {
220  unsigned int type = ELF32_R_TYPE(rela->r_info);
221  uint32_t locoffset = base_sect->flat_offset + rela->r_offset;
222  char* loc = (char*)(flat_buf + locoffset );
223 
224  char symbuf[30];
225  char* symname=""; // to printf: name of symbol
226  int ret = b_seek_read(strtaboff + sym->st_name, symbuf, sizeof(symbuf));
227  if (ret > 0) { symname=symbuf; symbuf[sizeof(symbuf)-1]=0; }
228 
229  switch(type) {
230  case R_ARM_ABS32:
231  {
232  flat_import_cur->offs = locoffset;
233  flat_import_cur->importidx = importidx;
234 
235  if ( FLAG_DUMP_RELOC )
236  printf( "R_ARM_ABS32: %p(%s+0x%x=%x): import_value=%d (sym:%s)+0x%x %d\n",
237  base_sect->base_addr+rela->r_offset, base_sect->name, rela->r_offset, locoffset,
238  importidx, symname, *(uint32_t*)loc, flat_import_count
239  );
240  flat_import_cur++;
242  }
243  break;
244 
245  default:
246  // Use only ABS32 because we can't be sure that module will be loaded not too far from core to PC24/THM_CALL
247  PRINTERR(stderr, "Only R_ARM_ABS32 relocations could be processed as imported symbol (%s). Please compile with -mlong-call or use manual import\n",symname);
248  return ELFFLT_UNHANDLED_RELOC;
249  }
250  return ELFFLT_OK;
251 }
int apply_realloc ( struct relevant_section base_sect,
struct elf32_rela rela,
struct relevant_section tgt_sect,
struct elf32_sym sym,
int  i 
)

Definiert in Zeile 18 der Datei elf-arm.c.

24 {
25  unsigned int type = ELF32_R_TYPE(rela->r_info);
26  uint32_t locoffset = base_sect->flat_offset + rela->r_offset;
27  char* loc = (char*)(flat_buf + locoffset );
28  uint32_t tgt_fulloffset = tgt_sect->flat_offset + sym->st_value; // full offset in flat target symbol
29 
30  int relindex = tgt_sect->number; // to printf: num of tgt segment
31  char symbuf[30];
32  char* symname=""; // to printf: name of symbol
33  char* reloc_name="";
34  int ret = b_seek_read(strtaboff + sym->st_name, symbuf, sizeof(symbuf));
35  if (ret > 0) { symname=symbuf; symbuf[sizeof(symbuf)-1]=0; }
36 
37 
39  uint32_t upper, lower, sign, j1, j2;
40  char* patch_name=""; // detected build-in function
41 
42 
43  if (rela->r_offset > base_sect->size - sizeof(uint32_t)) {
44  PRINTERR(stderr, "section %u(%s) reloc %u sym '%s': out of bounds relocation, offset %d size %u\n",
45  relindex, base_sect->name, i, symname,
46  rela->r_offset, base_sect->size);
47  return ELFFLT_OUTOF_RANGE;
48  }
49 
50  switch(type) {
51  case R_ARM_ABS32:
52  {
53  uint32_t addend = *(uint32_t*)loc;
54  *(uint32_t*)loc += tgt_fulloffset;
55 
56  if ( FLAG_DUMP_RELOC )
57  printf( "R_ARM_ABS32: %p(%s+0x%x=%x): ptr=%x [%s+0x%x+0x%x] sym:%s\n",
58  base_sect->base_addr+rela->r_offset, base_sect->name, rela->r_offset, locoffset,
59  tgt_sect->base_addr + addend + sym->st_value,
60  tgt_sect->name, sym->st_value, addend, symname
61  );
62 
63  if ( FLAG_VERBOSE)
64  printf("=== flt%p(reloc+%x: %x): [%x]=0x%x\n",flat_reloc_cur, (char*)flat_reloc_cur-(char*)flat_reloc, (char*)flat_reloc_cur-flat_buf, locoffset, *(uint32_t*)loc);
65  *flat_reloc_cur = locoffset;
68  }
69  break;
70 
71  case R_ARM_THM_CALL:
72  case R_ARM_THM_JUMP24: //needed on arm-none-eabi
73  upper = *(uint16_t *)loc;
74  lower = *(uint16_t *)(loc + 2);
75 
76  /*
77  * 25 bit signed address range (Thumb-2 BL and B.W
78  * instructions):
79  * S:I1:I2:imm10:imm11:0
80  * where:
81  * S = upper[10] = offset[24]
82  * I1 = ~(J1 ^ S) = offset[23]
83  * I2 = ~(J2 ^ S) = offset[22]
84  * imm10 = upper[9:0] = offset[21:12]
85  * imm11 = lower[10:0] = offset[11:1]
86  * J1 = lower[13]
87  * J2 = lower[11]
88  */
89  sign = (upper >> 10) & 1;
90  j1 = (lower >> 13) & 1;
91  j2 = (lower >> 11) & 1;
92  offset = (sign << 24) | ((~(j1 ^ sign) & 1) << 23) |
93  ((~(j2 ^ sign) & 1) << 22) |
94  ((upper & 0x03ff) << 12) |
95  ((lower & 0x07ff) << 1);
96  if (offset & 0x01000000)
97  offset -= 0x02000000;
98  offset += tgt_fulloffset - locoffset;
99 
100  /*
101  * For function symbols, only Thumb addresses are
102  * allowed (no interworking).
103  *
104  * For non-function symbols, the destination
105  * has no specific ARM/Thumb disposition, so
106  * the branch is resolved under the assumption
107  * that interworking is not required.
108  */
109  if ((ELF32_ST_TYPE(sym->st_info) == STT_FUNC &&
110  !(offset & 1)) ||
111  offset <= (int32_t)0xff000000 ||
112  offset >= (int32_t)0x01000000) {
113  PRINTERR(stderr, "section %u reloc %u sym '%s': relocation %u out of range (%#lx -> %#x)\n",
114  relindex, i, symname,
115  ELF32_R_TYPE(rela->r_info), locoffset,
116  sym->st_value);
117  return ELFFLT_OUTOF_RANGE;
118  }
119 
120  if ( FLAG_DUMP_RELOC )
121  printf( "R_ARM_THM_CALL: %p(%s+0x%x=%x): %04x %04x ptr=%x [loc%-d] sym:%s\n",
122  base_sect->base_addr+rela->r_offset, base_sect->name, rela->r_offset, locoffset,
123  upper, lower,
124  tgt_sect->base_addr+rela->r_offset+offset, offset,
125  symname);
126 
127  sign = (offset >> 24) & 1;
128  j1 = sign ^ (~(offset >> 23) & 1);
129  j2 = sign ^ (~(offset >> 22) & 1);
130  *(uint16_t *)loc = (uint16_t)((upper & 0xf800) | (sign << 10) |
131  ((offset >> 12) & 0x03ff));
132  *(uint16_t *)(loc + 2) = (uint16_t)((lower & 0xd000) |
133  (j1 << 13) | (j2 << 11) |
134  ((offset >> 1) & 0x07ff));
135  break;
136 
137  case R_ARM_PC24:
138  case R_ARM_JUMP24:
139  case R_ARM_CALL:
140  // R_ARM_PC24 is generated by Win arm-gcc. And in some buildin funcs change
141  // this pointer to different function. This part is emulate this behaviour.
142 
143  patch_name=0;
144  if ( strcmp(symname,"__div0") == 0 )
145  {
146  if ( locoffset == offs_divsi3_skip_div0_test )
147  patch_name=".divsi3_skip_div0_test";
148  else if ( locoffset == offs__aeabi_uidiv )
149  patch_name="__aeabi_uidiv";
150 
151  if ( !patch_name ) {
152  PRINTERR( stderr, "%s is requested from unusual place .text+0x%x\n", reloc_name,locoffset-text.flat_offset);
153  return ELFFLT_UNHANDLED_RELOC;
154  }
155 
156  // this is redirection to the new func
157  tgt_fulloffset = (text.flat_offset + offs_div0_from_arm);
158  // Falls through to next case - no break ***
159  }
160 
161  case R_ARM_PLT32:
162  // R_ARM_PLT32 is generated by linux arm-gcc and it doesn't change binary when instance into fixed adress
163 
164 // case R_ARM_CALL: // not needed
165 // case R_ARM_JUMP24: // not needed
166 
167  reloc_name = (type==R_ARM_PC24)?"R_ARM_PC24":"R_ARM_PLT32";
168 
169  offset = (*(uint32_t *)loc & 0x00ffffff) << 2;
170  if (offset & 0x02000000)
171  offset -= 0x04000000;
172 
173  offset += tgt_fulloffset - locoffset;
174 
175 /* it is possible to have offset close to upper border
176  if (offset & 3 ||
177  offset <= (int32_t)0xfe000000 ||
178  offset >= (int32_t)0x02000000) {
179  PRINTERR(stderr, "section %u reloc %u sym '%s': relocation %u out of range (%#lx -> %#x)\n",
180  relindex, i, symname,
181  ELF32_R_TYPE(rela->r_info), locoffset,
182  tgt_fulloffset);
183  return ELFFLT_OUTOF_RANGE;
184  }
185 */
186 
187  offset >>= 2;
188 
189  if ( FLAG_DUMP_RELOC )
190  {
191  printf( "%s: %p(%s+0x%x=%x): %08x ptr=%x [loc%-d] sym:%s\n", reloc_name,
192  base_sect->base_addr+rela->r_offset, base_sect->name, rela->r_offset, locoffset,
193  *(uint32_t *)loc,
194  base_sect->base_addr+rela->r_offset+offset*4, offset*4,
195  symname);
196  if ((type==R_ARM_PC24) && patch_name)
197  printf( "...Patched 0x%x(__div0)->0x%x (__div0_from_arm) for %s\n", sym->st_value, offs_div0_from_arm, patch_name);
198  }
199 
200  *(uint32_t *)loc &= 0xff000000;
201  *(uint32_t *)loc |= offset & 0x00ffffff;
202  break;
203  default:
204  PRINTERR(stderr, "Unknown relocation type %d\n",type);
205  return ELFFLT_UNHANDLED_RELOC;
206  }
207 
208  return ELFFLT_OK;
209 }

Variablen-Dokumentation

uint32_t offs__aeabi_uidiv

Definiert in Zeile 320 der Datei elfflt.c.

uint32_t offs_div0_from_arm

Definiert in Zeile 318 der Datei elfflt.c.

uint32_t offs_divsi3_skip_div0_test

Definiert in Zeile 319 der Datei elfflt.c.