Lines Matching +full:- +full:s

1 /*-
2 * Copyright (c) 2007-2010,2012 Kai Wang
37 ELFTC_VCSID("$Id: segments.c 3615 2018-05-17 04:12:24Z kaiwang27 $");
42 * elfcopy's segment handling is relatively simpler and less powerful than
44 * but never re-generated. As a result, if the input object has incorrect
45 * program headers, the output object's program headers will remain incorrect
51 * corresponding segment list(s) and return 1.
54 add_to_inseg_list(struct elfcopy *ecp, struct section *s) in add_to_inseg_list() argument
59 if (ecp->ophnum == 0) in add_to_inseg_list()
69 * segment(s)' v_sec queue. These information are later used to in add_to_inseg_list()
74 STAILQ_FOREACH(seg, &ecp->v_seg, seg_list) { in add_to_inseg_list()
75 if (s->off < seg->off || (s->vma < seg->vaddr && !s->pseudo)) in add_to_inseg_list()
77 if (s->off + s->sz > seg->off + seg->fsz && in add_to_inseg_list()
78 s->type != SHT_NOBITS) in add_to_inseg_list()
80 if (s->vma + s->sz > seg->vaddr + seg->msz) in add_to_inseg_list()
82 if (seg->type == PT_TLS && ((s->flags & SHF_TLS) == 0)) in add_to_inseg_list()
85 insert_to_inseg_list(seg, s); in add_to_inseg_list()
86 if (seg->type == PT_LOAD) in add_to_inseg_list()
87 s->seg = seg; in add_to_inseg_list()
88 else if (seg->type == PT_TLS) in add_to_inseg_list()
89 s->seg_tls = seg; in add_to_inseg_list()
90 if (s->pseudo) in add_to_inseg_list()
91 s->vma = seg->vaddr + (s->off - seg->off); in add_to_inseg_list()
92 if (seg->paddr > 0) in add_to_inseg_list()
93 s->lma = seg->paddr + (s->off - seg->off); in add_to_inseg_list()
95 s->lma = 0; in add_to_inseg_list()
105 struct section *s, *s0; in adjust_addr() local
114 TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { in adjust_addr()
116 /* Only adjust loadable section's address. */ in adjust_addr()
117 if (!s->loadable) in adjust_addr()
121 if (ecp->change_addr != 0) in adjust_addr()
122 s->vma += ecp->change_addr; in adjust_addr()
125 if (ecp->change_addr != 0 && s->seg != NULL && in adjust_addr()
126 s->seg->paddr > 0) in adjust_addr()
127 s->lma += ecp->change_addr; in adjust_addr()
133 TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { in adjust_addr()
135 if (!s->loadable) in adjust_addr()
142 sac = lookup_sec_act(ecp, s->name, 0); in adjust_addr()
145 vma = s->vma; in adjust_addr()
146 if (sac->setvma) in adjust_addr()
147 vma = sac->vma; in adjust_addr()
148 if (sac->vma_adjust != 0) in adjust_addr()
149 vma += sac->vma_adjust; in adjust_addr()
150 if (vma == s->vma) in adjust_addr()
157 if (s->seg == NULL) { in adjust_addr()
158 s->vma = vma; in adjust_addr()
173 printf("VMA for section %s: %#jx\n", s->name, vma); in adjust_addr()
176 if (vma % s->align != 0) in adjust_addr()
178 "section %s is not aligned to %ju", in adjust_addr()
179 (uintmax_t) vma, s->name, (uintmax_t) s->align); in adjust_addr()
181 if (vma < s->vma) { in adjust_addr()
183 if (vma < s->vma - s->seg->vaddr) in adjust_addr()
185 "section %s VMA to %#jx", s->name, in adjust_addr()
187 start = vma - (s->vma - s->seg->vaddr); in adjust_addr()
188 if (s == s->seg->v_sec[s->seg->nsec - 1]) in adjust_addr()
189 end = start + s->seg->msz; in adjust_addr()
191 end = s->seg->vaddr + s->seg->msz; in adjust_addr()
194 if (s == s->seg->v_sec[0]) in adjust_addr()
197 start = s->seg->vaddr; in adjust_addr()
198 end = vma + (s->seg->vaddr + s->seg->msz - s->vma); in adjust_addr()
201 "section %s VMA to %#jx", s->name, in adjust_addr()
206 printf("new extent for segment containing %s: (%#jx,%#jx)\n", in adjust_addr()
207 s->name, start, end); in adjust_addr()
210 STAILQ_FOREACH(seg, &ecp->v_seg, seg_list) { in adjust_addr()
211 if (seg == s->seg || seg->type != PT_LOAD) in adjust_addr()
213 if (start > seg->vaddr + seg->msz) in adjust_addr()
215 if (end < seg->vaddr) in adjust_addr()
218 "section %s overlaps with segment(%#jx,%#jx)", in adjust_addr()
219 s->name, (uintmax_t) seg->vaddr, in adjust_addr()
220 (uintmax_t) (seg->vaddr + seg->msz)); in adjust_addr()
227 if (vma < s->vma) { in adjust_addr()
234 dl = s->vma - vma; in adjust_addr()
235 for (i = 0; i < s->seg->nsec; i++) { in adjust_addr()
236 s0 = s->seg->v_sec[i]; in adjust_addr()
237 s0->vma -= dl; in adjust_addr()
239 printf("section %s VMA set to %#jx\n", in adjust_addr()
240 s0->name, (uintmax_t) s0->vma); in adjust_addr()
242 if (s0 == s) in adjust_addr()
245 for (i = i + 1; i < s->seg->nsec; i++) { in adjust_addr()
246 s0 = s->seg->v_sec[i]; in adjust_addr()
247 s0->off += dl; in adjust_addr()
249 printf("section %s offset set to %#jx\n", in adjust_addr()
250 s0->name, (uintmax_t) s0->off); in adjust_addr()
261 dl = vma - s->vma; in adjust_addr()
262 for (i = 0; i < s->seg->nsec; i++) in adjust_addr()
263 if (s->seg->v_sec[i] == s) in adjust_addr()
265 if (i >= s->seg->nsec) in adjust_addr()
266 errx(EXIT_FAILURE, "Internal: section `%s' not" in adjust_addr()
268 s->name); in adjust_addr()
269 for (; i < s->seg->nsec; i++) { in adjust_addr()
270 s0 = s->seg->v_sec[i]; in adjust_addr()
271 s0->vma += dl; in adjust_addr()
273 printf("section %s VMA set to %#jx\n", in adjust_addr()
274 s0->name, (uintmax_t) s0->lma); in adjust_addr()
276 if (s != s->seg->v_sec[0]) { in adjust_addr()
277 s0->off += dl; in adjust_addr()
279 printf("section %s offset set to %#jx\n", in adjust_addr()
280 s0->name, (uintmax_t) s0->off); in adjust_addr()
291 if (ecp->pad_to != 0) { in adjust_addr()
296 s = NULL; in adjust_addr()
297 STAILQ_FOREACH(seg, &ecp->v_seg, seg_list) { in adjust_addr()
298 if (seg->type != PT_LOAD) in adjust_addr()
300 for (i = seg->nsec - 1; i >= 0; i--) in adjust_addr()
301 if (seg->v_sec[i]->type != SHT_NOBITS) in adjust_addr()
305 if (s == NULL) in adjust_addr()
306 s = seg->v_sec[i]; in adjust_addr()
308 s0 = seg->v_sec[i]; in adjust_addr()
309 if (s0->vma > s->vma) in adjust_addr()
310 s = s0; in adjust_addr()
314 if (s == NULL) in adjust_addr()
318 if (ecp->pad_to <= s->vma + s->sz) in adjust_addr()
321 s->pad_sz = ecp->pad_to - (s->vma + s->sz); in adjust_addr()
323 printf("pad section %s VMA to address %#jx by %#jx\n", s->name, in adjust_addr()
324 (uintmax_t) ecp->pad_to, (uintmax_t) s->pad_sz); in adjust_addr()
334 TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { in adjust_addr()
337 * Only loadable section that's inside a segment can have in adjust_addr()
341 if (!s->loadable || s->seg == NULL || s->seg->paddr == 0) in adjust_addr()
348 sac = lookup_sec_act(ecp, s->name, 0); in adjust_addr()
351 if (!sac->setlma && sac->lma_adjust == 0) in adjust_addr()
353 lma = s->lma; in adjust_addr()
354 if (sac->setlma) in adjust_addr()
355 lma = sac->lma; in adjust_addr()
356 if (sac->lma_adjust != 0) in adjust_addr()
357 lma += sac->lma_adjust; in adjust_addr()
358 if (lma == s->lma) in adjust_addr()
362 printf("LMA for section %s: %#jx\n", s->name, lma); in adjust_addr()
366 if (lma % s->align != 0) in adjust_addr()
368 "section %s is not aligned to %ju", in adjust_addr()
369 (uintmax_t) lma, s->name, (uintmax_t) s->align); in adjust_addr()
375 if (lma < s->lma) { in adjust_addr()
381 dl = s->lma - lma; in adjust_addr()
382 for (i = 0; i < s->seg->nsec; i++) { in adjust_addr()
383 s0 = s->seg->v_sec[i]; in adjust_addr()
384 s0->lma -= dl; in adjust_addr()
386 printf("section %s LMA set to %#jx\n", in adjust_addr()
387 s0->name, (uintmax_t) s0->lma); in adjust_addr()
389 if (s0 == s) in adjust_addr()
398 dl = lma - s->lma; in adjust_addr()
399 for (i = 0; i < s->seg->nsec; i++) in adjust_addr()
400 if (s->seg->v_sec[i] == s) in adjust_addr()
402 if (i >= s->seg->nsec) in adjust_addr()
403 errx(EXIT_FAILURE, "Internal: section `%s' not" in adjust_addr()
405 s->name); in adjust_addr()
406 for (; i < s->seg->nsec; i++) { in adjust_addr()
407 s0 = s->seg->v_sec[i]; in adjust_addr()
408 s0->lma += dl; in adjust_addr()
410 printf("section %s LMA set to %#jx\n", in adjust_addr()
411 s0->name, (uintmax_t) s0->lma); in adjust_addr()
421 if ((ecp->flags & NO_CHANGE_WARN) == 0) { in adjust_addr()
422 STAILQ_FOREACH(sac, &ecp->v_sac, sac_list) { in adjust_addr()
423 if (!sac->setvma && !sac->setlma && in adjust_addr()
424 !sac->vma_adjust && !sac->lma_adjust) in adjust_addr()
427 TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { in adjust_addr()
428 if (s->pseudo || s->name == NULL) in adjust_addr()
430 if (!strcmp(s->name, sac->name)) { in adjust_addr()
436 warnx("cannot find section `%s'", sac->name); in adjust_addr()
444 struct section *s; in insert_to_inseg_list() local
447 seg->nsec++; in insert_to_inseg_list()
448 seg->v_sec = realloc(seg->v_sec, seg->nsec * sizeof(*seg->v_sec)); in insert_to_inseg_list()
449 if (seg->v_sec == NULL) in insert_to_inseg_list()
456 for (i = seg->nsec - 1; i > 0; i--) { in insert_to_inseg_list()
457 s = seg->v_sec[i - 1]; in insert_to_inseg_list()
458 if (sec->off >= s->off) { in insert_to_inseg_list()
459 seg->v_sec[i] = sec; in insert_to_inseg_list()
462 seg->v_sec[i] = s; in insert_to_inseg_list()
465 seg->v_sec[0] = sec; in insert_to_inseg_list()
475 if (elf_getphnum(ecp->ein, &iphnum) == 0) in setup_phdr()
476 errx(EXIT_FAILURE, "elf_getphnum failed: %s", in setup_phdr()
477 elf_errmsg(-1)); in setup_phdr()
479 ecp->ophnum = ecp->iphnum = iphnum; in setup_phdr()
483 /* If --only-keep-debug is specified, discard all program headers. */ in setup_phdr()
484 if (ecp->strip == STRIP_NONDEBUG) { in setup_phdr()
485 ecp->ophnum = 0; in setup_phdr()
490 if (gelf_getphdr(ecp->ein, i, &iphdr) != &iphdr) in setup_phdr()
491 errx(EXIT_FAILURE, "gelf_getphdr failed: %s", in setup_phdr()
492 elf_errmsg(-1)); in setup_phdr()
495 seg->vaddr = iphdr.p_vaddr; in setup_phdr()
496 seg->paddr = iphdr.p_paddr; in setup_phdr()
497 seg->off = iphdr.p_offset; in setup_phdr()
498 seg->fsz = iphdr.p_filesz; in setup_phdr()
499 seg->msz = iphdr.p_memsz; in setup_phdr()
500 seg->type = iphdr.p_type; in setup_phdr()
501 STAILQ_INSERT_TAIL(&ecp->v_seg, seg, seg_list); in setup_phdr()
509 struct section *s; in copy_phdr() local
513 STAILQ_FOREACH(seg, &ecp->v_seg, seg_list) { in copy_phdr()
514 if (seg->type == PT_PHDR) { in copy_phdr()
515 if (!TAILQ_EMPTY(&ecp->v_sec)) { in copy_phdr()
516 s = TAILQ_FIRST(&ecp->v_sec); in copy_phdr()
517 if (s->pseudo) { in copy_phdr()
518 seg->vaddr = s->vma + in copy_phdr()
519 gelf_fsize(ecp->eout, ELF_T_EHDR, in copy_phdr()
521 seg->paddr = s->lma + in copy_phdr()
522 gelf_fsize(ecp->eout, ELF_T_EHDR, in copy_phdr()
526 seg->fsz = seg->msz = gelf_fsize(ecp->eout, ELF_T_PHDR, in copy_phdr()
527 ecp->ophnum, EV_CURRENT); in copy_phdr()
531 if (seg->nsec > 0) { in copy_phdr()
532 s = seg->v_sec[0]; in copy_phdr()
533 seg->vaddr = s->vma; in copy_phdr()
534 seg->paddr = s->lma; in copy_phdr()
537 seg->fsz = seg->msz = 0; in copy_phdr()
538 for (i = 0; i < seg->nsec; i++) { in copy_phdr()
539 s = seg->v_sec[i]; in copy_phdr()
540 seg->msz = s->vma + s->sz - seg->vaddr; in copy_phdr()
541 if (s->type != SHT_NOBITS) in copy_phdr()
542 seg->fsz = s->off + s->sz - seg->off; in copy_phdr()
551 if (gelf_newphdr(ecp->eout, ecp->ophnum) == NULL) in copy_phdr()
552 errx(EXIT_FAILURE, "gelf_newphdr() failed: %s", in copy_phdr()
553 elf_errmsg(-1)); in copy_phdr()
557 * ehdr. It's necessary because later we will call gelf_getphdr(), in copy_phdr()
560 if (elf_update(ecp->eout, ELF_C_NULL) < 0) in copy_phdr()
561 errx(EXIT_FAILURE, "elf_update() failed: %s", elf_errmsg(-1)); in copy_phdr()
568 STAILQ_FOREACH(seg, &ecp->v_seg, seg_list) { in copy_phdr()
569 if (i >= ecp->iphnum) in copy_phdr()
571 if (gelf_getphdr(ecp->ein, i, &iphdr) != &iphdr) in copy_phdr()
572 errx(EXIT_FAILURE, "gelf_getphdr failed: %s", in copy_phdr()
573 elf_errmsg(-1)); in copy_phdr()
574 if (gelf_getphdr(ecp->eout, i, &ophdr) != &ophdr) in copy_phdr()
575 errx(EXIT_FAILURE, "gelf_getphdr failed: %s", in copy_phdr()
576 elf_errmsg(-1)); in copy_phdr()
579 ophdr.p_vaddr = seg->vaddr; in copy_phdr()
580 ophdr.p_paddr = seg->paddr; in copy_phdr()
583 ophdr.p_offset = seg->off; in copy_phdr()
584 ophdr.p_filesz = seg->fsz; in copy_phdr()
585 ophdr.p_memsz = seg->msz; in copy_phdr()
586 if (!gelf_update_phdr(ecp->eout, i, &ophdr)) in copy_phdr()
587 errx(EXIT_FAILURE, "gelf_update_phdr failed: %s", in copy_phdr()
588 elf_errmsg(-1)); in copy_phdr()