diff options
Diffstat (limited to 'utils')
-rw-r--r-- | utils/imxtools/sbtools/elf.c | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/utils/imxtools/sbtools/elf.c b/utils/imxtools/sbtools/elf.c index 53adcd1160..35bc1605d3 100644 --- a/utils/imxtools/sbtools/elf.c +++ b/utils/imxtools/sbtools/elf.c | |||
@@ -217,9 +217,99 @@ void elf_add_fill_section(struct elf_params_t *params, | |||
217 | sec->pattern = pattern; | 217 | sec->pattern = pattern; |
218 | } | 218 | } |
219 | 219 | ||
220 | /* sort by increasing type and then increasing address */ | ||
221 | static int elf_simplify_compare(const void *a, const void *b) | ||
222 | { | ||
223 | const struct elf_section_t *sa = a; | ||
224 | const struct elf_section_t *sb = b; | ||
225 | if(sa->type != sb->type) | ||
226 | return sa->type - sb->type; | ||
227 | return sa->addr - sb->addr; | ||
228 | } | ||
229 | |||
220 | void elf_simplify(struct elf_params_t *params) | 230 | void elf_simplify(struct elf_params_t *params) |
221 | { | 231 | { |
232 | /** find all sections of the same times which are contiguous and merge them */ | ||
233 | |||
234 | /* count sections */ | ||
235 | int nr_sections = 0; | ||
236 | struct elf_section_t *cur_sec = params->first_section; | ||
237 | while(cur_sec) | ||
238 | { | ||
239 | nr_sections++; | ||
240 | cur_sec = cur_sec->next; | ||
241 | } | ||
222 | 242 | ||
243 | /* put all sections in an array and free list */ | ||
244 | struct elf_section_t *sections = malloc(sizeof(struct elf_section_t) * nr_sections); | ||
245 | cur_sec = params->first_section; | ||
246 | for(int i = 0; i < nr_sections; i++) | ||
247 | { | ||
248 | memcpy(§ions[i], cur_sec, sizeof(struct elf_section_t)); | ||
249 | struct elf_section_t *old = cur_sec; | ||
250 | cur_sec = cur_sec->next; | ||
251 | free(old); | ||
252 | } | ||
253 | |||
254 | /* sort them by type and increasing addresses */ | ||
255 | qsort(sections, nr_sections, sizeof(struct elf_section_t), &elf_simplify_compare); | ||
256 | |||
257 | /* merge them ! */ | ||
258 | cur_sec = §ions[0]; | ||
259 | for(int i = 1; i < nr_sections; i++) | ||
260 | { | ||
261 | /* different type => no */ | ||
262 | if(sections[i].type != cur_sec->type) | ||
263 | goto Lnext; | ||
264 | /* (for fill) different pattern => no */ | ||
265 | if(sections[i].type == EST_FILL && sections[i].pattern != cur_sec->pattern) | ||
266 | goto Lnext; | ||
267 | /* not contiguous => no */ | ||
268 | if(sections[i].addr != cur_sec->addr + cur_sec->size) | ||
269 | goto Lnext; | ||
270 | /* merge !! */ | ||
271 | if(sections[i].type == EST_FILL) | ||
272 | { | ||
273 | cur_sec->size += sections[i].size; | ||
274 | sections[i].size = 0; // will be ignored by rebuilding (see below) | ||
275 | } | ||
276 | else if(sections[i].type == EST_LOAD) | ||
277 | { | ||
278 | // merge data also | ||
279 | void *data = malloc(cur_sec->size + sections[i].size); | ||
280 | memcpy(data, cur_sec->section, cur_sec->size); | ||
281 | memcpy(data + cur_sec->size, sections[i].section, sections[i].size); | ||
282 | free(cur_sec->section); | ||
283 | free(sections[i].section); | ||
284 | cur_sec->section = data; | ||
285 | cur_sec->size += sections[i].size; | ||
286 | sections[i].size = 0; // will be ignored by rebuilding (see below) | ||
287 | } | ||
288 | continue; | ||
289 | |||
290 | /* update current section to consider */ | ||
291 | Lnext: | ||
292 | cur_sec = §ions[i]; | ||
293 | } | ||
294 | |||
295 | /* put back on a list and free array */ | ||
296 | struct elf_section_t **prev_ptr = ¶ms->first_section; | ||
297 | struct elf_section_t *prev_sec = NULL; | ||
298 | for(int i = 0; i < nr_sections; i++) | ||
299 | { | ||
300 | /* skip empty sections produced by simplification */ | ||
301 | if(sections[i].size == 0) | ||
302 | continue; | ||
303 | |||
304 | struct elf_section_t *sec = malloc(sizeof(struct elf_section_t)); | ||
305 | memcpy(sec, §ions[i], sizeof(struct elf_section_t)); | ||
306 | *prev_ptr = sec; | ||
307 | prev_ptr = &sec->next; | ||
308 | prev_sec = sec; | ||
309 | } | ||
310 | *prev_ptr = NULL; | ||
311 | params->last_section = prev_sec; | ||
312 | free(sections); | ||
223 | } | 313 | } |
224 | 314 | ||
225 | void elf_write_file(struct elf_params_t *params, elf_write_fn_t write, | 315 | void elf_write_file(struct elf_params_t *params, elf_write_fn_t write, |