1a85fe12eSEd Maste /*- 2a85fe12eSEd Maste * Copyright (c) 2007-2010,2012 Kai Wang 3a85fe12eSEd Maste * All rights reserved. 4a85fe12eSEd Maste * 5a85fe12eSEd Maste * Redistribution and use in source and binary forms, with or without 6a85fe12eSEd Maste * modification, are permitted provided that the following conditions 7a85fe12eSEd Maste * are met: 8a85fe12eSEd Maste * 1. Redistributions of source code must retain the above copyright 9a85fe12eSEd Maste * notice, this list of conditions and the following disclaimer. 10a85fe12eSEd Maste * 2. Redistributions in binary form must reproduce the above copyright 11a85fe12eSEd Maste * notice, this list of conditions and the following disclaimer in the 12a85fe12eSEd Maste * documentation and/or other materials provided with the distribution. 13a85fe12eSEd Maste * 14a85fe12eSEd Maste * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15a85fe12eSEd Maste * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16a85fe12eSEd Maste * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17a85fe12eSEd Maste * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18a85fe12eSEd Maste * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19a85fe12eSEd Maste * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20a85fe12eSEd Maste * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21a85fe12eSEd Maste * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22a85fe12eSEd Maste * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23a85fe12eSEd Maste * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24a85fe12eSEd Maste * SUCH DAMAGE. 25a85fe12eSEd Maste */ 26a85fe12eSEd Maste 27a85fe12eSEd Maste #include <sys/queue.h> 28a85fe12eSEd Maste #include <err.h> 29a85fe12eSEd Maste #include <gelf.h> 3050f69bfbSEd Maste #include <stdint.h> 31a85fe12eSEd Maste #include <stdio.h> 32a85fe12eSEd Maste #include <stdlib.h> 33a85fe12eSEd Maste #include <string.h> 34a85fe12eSEd Maste 35a85fe12eSEd Maste #include "elfcopy.h" 36a85fe12eSEd Maste 37*b00fe64fSEd Maste ELFTC_VCSID("$Id: segments.c 3196 2015-05-12 17:33:48Z emaste $"); 38a85fe12eSEd Maste 39a85fe12eSEd Maste static void insert_to_inseg_list(struct segment *seg, struct section *sec); 40a85fe12eSEd Maste 41a85fe12eSEd Maste /* 42a85fe12eSEd Maste * elfcopy's segment handling is relatively simpler and less powerful than 43a85fe12eSEd Maste * libbfd. Program headers are modified or copied from input to output objects, 44a85fe12eSEd Maste * but never re-generated. As a result, if the input object has incorrect 45a85fe12eSEd Maste * program headers, the output object's program headers will remain incorrect 46a85fe12eSEd Maste * or become even worse. 47a85fe12eSEd Maste */ 48a85fe12eSEd Maste 49a85fe12eSEd Maste /* 50a85fe12eSEd Maste * Check whether a section is "loadable". If so, add it to the 51a85fe12eSEd Maste * corresponding segment list(s) and return 1. 52a85fe12eSEd Maste */ 53a85fe12eSEd Maste int 54a85fe12eSEd Maste add_to_inseg_list(struct elfcopy *ecp, struct section *s) 55a85fe12eSEd Maste { 56a85fe12eSEd Maste struct segment *seg; 57a85fe12eSEd Maste int loadable; 58a85fe12eSEd Maste 59a85fe12eSEd Maste if (ecp->ophnum == 0) 60a85fe12eSEd Maste return (0); 61a85fe12eSEd Maste 62a85fe12eSEd Maste /* 63a85fe12eSEd Maste * Segment is a different view of an ELF object. One segment can 64a85fe12eSEd Maste * contain one or more sections, and one section can be included 65a85fe12eSEd Maste * in one or more segments, or not included in any segment at all. 66a85fe12eSEd Maste * We call those sections which can be found in one or more segments 67a85fe12eSEd Maste * "loadable" sections, and call the rest "unloadable" sections. 68a85fe12eSEd Maste * We keep track of "loadable" sections in their containing 69a85fe12eSEd Maste * segment(s)' v_sec queue. These information are later used to 70a85fe12eSEd Maste * recalculate the extents of segments, when sections are removed, 71a85fe12eSEd Maste * for example. 72a85fe12eSEd Maste */ 73a85fe12eSEd Maste loadable = 0; 74a85fe12eSEd Maste STAILQ_FOREACH(seg, &ecp->v_seg, seg_list) { 75cf781b2eSEd Maste if (s->off < seg->off || (s->vma < seg->addr && !s->pseudo)) 76a85fe12eSEd Maste continue; 77a85fe12eSEd Maste if (s->off + s->sz > seg->off + seg->fsz && 78a85fe12eSEd Maste s->type != SHT_NOBITS) 79a85fe12eSEd Maste continue; 80a85fe12eSEd Maste if (s->off + s->sz > seg->off + seg->msz) 81a85fe12eSEd Maste continue; 82cf781b2eSEd Maste if (s->vma + s->sz > seg->addr + seg->msz) 83cf781b2eSEd Maste continue; 84a85fe12eSEd Maste 85a85fe12eSEd Maste insert_to_inseg_list(seg, s); 86a85fe12eSEd Maste if (seg->type == PT_LOAD) 87a85fe12eSEd Maste s->seg = seg; 884a85c691SEd Maste else if (seg->type == PT_TLS) 894a85c691SEd Maste s->seg_tls = seg; 90a85fe12eSEd Maste s->lma = seg->addr + (s->off - seg->off); 91a85fe12eSEd Maste loadable = 1; 92a85fe12eSEd Maste } 93a85fe12eSEd Maste 94a85fe12eSEd Maste return (loadable); 95a85fe12eSEd Maste } 96a85fe12eSEd Maste 97a85fe12eSEd Maste void 98a85fe12eSEd Maste adjust_addr(struct elfcopy *ecp) 99a85fe12eSEd Maste { 100a85fe12eSEd Maste struct section *s, *s0; 101a85fe12eSEd Maste struct segment *seg; 102a85fe12eSEd Maste struct sec_action *sac; 103cf781b2eSEd Maste uint64_t dl, lma, start, end; 104a85fe12eSEd Maste int found, i; 105a85fe12eSEd Maste 106a85fe12eSEd Maste /* 107a85fe12eSEd Maste * Apply VMA and global LMA changes in the first iteration. 108a85fe12eSEd Maste */ 109a85fe12eSEd Maste TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { 110a85fe12eSEd Maste 111a85fe12eSEd Maste /* Only adjust loadable section's address. */ 112a85fe12eSEd Maste if (!s->loadable || s->seg == NULL) 113a85fe12eSEd Maste continue; 114a85fe12eSEd Maste 115a85fe12eSEd Maste /* Apply global LMA adjustment. */ 116a85fe12eSEd Maste if (ecp->change_addr != 0) 117a85fe12eSEd Maste s->lma += ecp->change_addr; 118a85fe12eSEd Maste 119a85fe12eSEd Maste if (!s->pseudo) { 120a85fe12eSEd Maste /* Apply global VMA adjustment. */ 121a85fe12eSEd Maste if (ecp->change_addr != 0) 122a85fe12eSEd Maste s->vma += ecp->change_addr; 123a85fe12eSEd Maste 124a85fe12eSEd Maste /* Apply section VMA adjustment. */ 125a85fe12eSEd Maste sac = lookup_sec_act(ecp, s->name, 0); 126a85fe12eSEd Maste if (sac == NULL) 127a85fe12eSEd Maste continue; 128a85fe12eSEd Maste if (sac->setvma) 129a85fe12eSEd Maste s->vma = sac->vma; 130a85fe12eSEd Maste if (sac->vma_adjust != 0) 131a85fe12eSEd Maste s->vma += sac->vma_adjust; 132a85fe12eSEd Maste } 133a85fe12eSEd Maste } 134a85fe12eSEd Maste 135a85fe12eSEd Maste /* 136a85fe12eSEd Maste * Apply sections LMA change in the second iteration. 137a85fe12eSEd Maste */ 138a85fe12eSEd Maste TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { 139a85fe12eSEd Maste 140a85fe12eSEd Maste /* Only adjust loadable section's LMA. */ 141a85fe12eSEd Maste if (!s->loadable || s->seg == NULL) 142a85fe12eSEd Maste continue; 143a85fe12eSEd Maste 144a85fe12eSEd Maste /* 145a85fe12eSEd Maste * Check if there is a LMA change request for this 146a85fe12eSEd Maste * section. 147a85fe12eSEd Maste */ 148a85fe12eSEd Maste sac = lookup_sec_act(ecp, s->name, 0); 149a85fe12eSEd Maste if (sac == NULL) 150a85fe12eSEd Maste continue; 151a85fe12eSEd Maste if (!sac->setlma && sac->lma_adjust == 0) 152a85fe12eSEd Maste continue; 153a85fe12eSEd Maste lma = s->lma; 154a85fe12eSEd Maste if (sac->setlma) 155a85fe12eSEd Maste lma = sac->lma; 156a85fe12eSEd Maste if (sac->lma_adjust != 0) 157a85fe12eSEd Maste lma += sac->lma_adjust; 158a85fe12eSEd Maste if (lma == s->lma) 159a85fe12eSEd Maste continue; 160a85fe12eSEd Maste 161a85fe12eSEd Maste /* 162a85fe12eSEd Maste * Check if the LMA change is viable. 163a85fe12eSEd Maste * 164a85fe12eSEd Maste * 1. Check if the new LMA is properly aligned accroding to 165a85fe12eSEd Maste * section alignment. 166a85fe12eSEd Maste * 167a85fe12eSEd Maste * 2. Compute the new extent of segment that contains this 168a85fe12eSEd Maste * section, make sure it doesn't overlap with other 169a85fe12eSEd Maste * segments. 170a85fe12eSEd Maste */ 171a85fe12eSEd Maste #ifdef DEBUG 172a85fe12eSEd Maste printf("LMA for section %s: %#jx\n", s->name, lma); 173a85fe12eSEd Maste #endif 174a85fe12eSEd Maste 175a85fe12eSEd Maste if (lma % s->align != 0) 176a85fe12eSEd Maste errx(EXIT_FAILURE, "The load address %#jx for " 177a85fe12eSEd Maste "section %s is not aligned to %ju", 178a85fe12eSEd Maste (uintmax_t) lma, s->name, s->align); 179a85fe12eSEd Maste 180a85fe12eSEd Maste if (lma < s->lma) { 181a85fe12eSEd Maste /* Move section to lower address. */ 182a85fe12eSEd Maste if (lma < s->lma - s->seg->addr) 183a85fe12eSEd Maste errx(EXIT_FAILURE, "Not enough space to move " 184a85fe12eSEd Maste "section %s load address to %#jx", s->name, 185a85fe12eSEd Maste (uintmax_t) lma); 186a85fe12eSEd Maste start = lma - (s->lma - s->seg->addr); 187a85fe12eSEd Maste if (s == s->seg->v_sec[s->seg->nsec - 1]) 188a85fe12eSEd Maste end = start + s->seg->msz; 189a85fe12eSEd Maste else 190a85fe12eSEd Maste end = s->seg->addr + s->seg->msz; 191a85fe12eSEd Maste 192a85fe12eSEd Maste } else { 193a85fe12eSEd Maste /* Move section to upper address. */ 194a85fe12eSEd Maste if (s == s->seg->v_sec[0]) 195a85fe12eSEd Maste start = lma; 196a85fe12eSEd Maste else 197a85fe12eSEd Maste start = s->seg->addr; 198a85fe12eSEd Maste end = lma + (s->seg->addr + s->seg->msz - s->lma); 199a85fe12eSEd Maste if (end < start) 200a85fe12eSEd Maste errx(EXIT_FAILURE, "Not enough space to move " 201a85fe12eSEd Maste "section %s load address to %#jx", s->name, 202a85fe12eSEd Maste (uintmax_t) lma); 203a85fe12eSEd Maste } 204a85fe12eSEd Maste 205a85fe12eSEd Maste #ifdef DEBUG 206a85fe12eSEd Maste printf("new extent for segment containing %s: (%#jx,%#jx)\n", 207a85fe12eSEd Maste s->name, start, end); 208a85fe12eSEd Maste #endif 209a85fe12eSEd Maste 210a85fe12eSEd Maste STAILQ_FOREACH(seg, &ecp->v_seg, seg_list) { 211a85fe12eSEd Maste if (seg == s->seg || seg->type != PT_LOAD) 212a85fe12eSEd Maste continue; 213a85fe12eSEd Maste if (start > seg->addr + seg->msz) 214a85fe12eSEd Maste continue; 215a85fe12eSEd Maste if (end < seg->addr) 216a85fe12eSEd Maste continue; 217a85fe12eSEd Maste errx(EXIT_FAILURE, "The extent of segment containing " 218a85fe12eSEd Maste "section %s overlaps with segment(%#jx,%#jx)", 219a85fe12eSEd Maste s->name, seg->addr, seg->addr + seg->msz); 220a85fe12eSEd Maste } 221a85fe12eSEd Maste 222a85fe12eSEd Maste /* 223a85fe12eSEd Maste * Update section LMA and file offset. 224a85fe12eSEd Maste */ 225a85fe12eSEd Maste 226a85fe12eSEd Maste if (lma < s->lma) { 227a85fe12eSEd Maste /* 228a85fe12eSEd Maste * To move a section to lower load address, we decrease 229a85fe12eSEd Maste * the load addresses of the section and all the 230a85fe12eSEd Maste * sections that are before it, and we increase the 231a85fe12eSEd Maste * file offsets of all the sections that are after it. 232a85fe12eSEd Maste */ 233a85fe12eSEd Maste dl = s->lma - lma; 234a85fe12eSEd Maste for (i = 0; i < s->seg->nsec; i++) { 235a85fe12eSEd Maste s0 = s->seg->v_sec[i]; 236a85fe12eSEd Maste s0->lma -= dl; 237a85fe12eSEd Maste #ifdef DEBUG 238a85fe12eSEd Maste printf("section %s LMA set to %#jx\n", 239a85fe12eSEd Maste s0->name, (uintmax_t) s0->lma); 240a85fe12eSEd Maste #endif 241a85fe12eSEd Maste if (s0 == s) 242a85fe12eSEd Maste break; 243a85fe12eSEd Maste } 244a85fe12eSEd Maste for (i = i + 1; i < s->seg->nsec; i++) { 245a85fe12eSEd Maste s0 = s->seg->v_sec[i]; 246a85fe12eSEd Maste s0->off += dl; 247a85fe12eSEd Maste #ifdef DEBUG 248a85fe12eSEd Maste printf("section %s offset set to %#jx\n", 249a85fe12eSEd Maste s0->name, (uintmax_t) s0->off); 250a85fe12eSEd Maste #endif 251a85fe12eSEd Maste } 252a85fe12eSEd Maste } else { 253a85fe12eSEd Maste /* 254a85fe12eSEd Maste * To move a section to upper load address, we increase 255a85fe12eSEd Maste * the load addresses of the section and all the 256a85fe12eSEd Maste * sections that are after it, and we increase the 257a85fe12eSEd Maste * their file offsets too unless the section in question 258a85fe12eSEd Maste * is the first in its containing segment. 259a85fe12eSEd Maste */ 260a85fe12eSEd Maste dl = lma - s->lma; 261a85fe12eSEd Maste for (i = 0; i < s->seg->nsec; i++) 262a85fe12eSEd Maste if (s->seg->v_sec[i] == s) 263a85fe12eSEd Maste break; 264a85fe12eSEd Maste if (i >= s->seg->nsec) 265a85fe12eSEd Maste errx(EXIT_FAILURE, "Internal: section `%s' not" 266a85fe12eSEd Maste " found in its containing segement", 267a85fe12eSEd Maste s->name); 268a85fe12eSEd Maste for (; i < s->seg->nsec; i++) { 269a85fe12eSEd Maste s0 = s->seg->v_sec[i]; 270a85fe12eSEd Maste s0->lma += dl; 271a85fe12eSEd Maste #ifdef DEBUG 272a85fe12eSEd Maste printf("section %s LMA set to %#jx\n", 273a85fe12eSEd Maste s0->name, (uintmax_t) s0->lma); 274a85fe12eSEd Maste #endif 275a85fe12eSEd Maste if (s != s->seg->v_sec[0]) { 276a85fe12eSEd Maste s0->off += dl; 277a85fe12eSEd Maste #ifdef DEBUG 278a85fe12eSEd Maste printf("section %s offset set to %#jx\n", 279a85fe12eSEd Maste s0->name, (uintmax_t) s0->off); 280a85fe12eSEd Maste #endif 281a85fe12eSEd Maste } 282a85fe12eSEd Maste } 283a85fe12eSEd Maste } 284a85fe12eSEd Maste } 285a85fe12eSEd Maste 286a85fe12eSEd Maste /* 287a85fe12eSEd Maste * Apply load address padding. 288a85fe12eSEd Maste */ 289a85fe12eSEd Maste 290a85fe12eSEd Maste if (ecp->pad_to != 0) { 291a85fe12eSEd Maste 292a85fe12eSEd Maste /* 293a85fe12eSEd Maste * Find the section with highest load address. 294a85fe12eSEd Maste */ 295a85fe12eSEd Maste 296a85fe12eSEd Maste s = NULL; 297a85fe12eSEd Maste STAILQ_FOREACH(seg, &ecp->v_seg, seg_list) { 298a85fe12eSEd Maste if (seg->type != PT_LOAD) 299a85fe12eSEd Maste continue; 300a85fe12eSEd Maste for (i = seg->nsec - 1; i >= 0; i--) 301a85fe12eSEd Maste if (seg->v_sec[i]->type != SHT_NOBITS) 302a85fe12eSEd Maste break; 303a85fe12eSEd Maste if (i < 0) 304a85fe12eSEd Maste continue; 305a85fe12eSEd Maste if (s == NULL) 306a85fe12eSEd Maste s = seg->v_sec[i]; 307a85fe12eSEd Maste else { 308a85fe12eSEd Maste s0 = seg->v_sec[i]; 309a85fe12eSEd Maste if (s0->lma > s->lma) 310a85fe12eSEd Maste s = s0; 311a85fe12eSEd Maste } 312a85fe12eSEd Maste } 313a85fe12eSEd Maste 314a85fe12eSEd Maste if (s == NULL) 315a85fe12eSEd Maste goto issue_warn; 316a85fe12eSEd Maste 317a85fe12eSEd Maste /* No need to pad if the pad_to address is lower. */ 318a85fe12eSEd Maste if (ecp->pad_to <= s->lma + s->sz) 319a85fe12eSEd Maste goto issue_warn; 320a85fe12eSEd Maste 321a85fe12eSEd Maste s->pad_sz = ecp->pad_to - (s->lma + s->sz); 322a85fe12eSEd Maste #ifdef DEBUG 323a85fe12eSEd Maste printf("pad section %s load to address %#jx by %#jx\n", s->name, 324a85fe12eSEd Maste (uintmax_t) ecp->pad_to, (uintmax_t) s->pad_sz); 325a85fe12eSEd Maste #endif 326a85fe12eSEd Maste } 327a85fe12eSEd Maste 328a85fe12eSEd Maste issue_warn: 329a85fe12eSEd Maste 330a85fe12eSEd Maste /* 331a85fe12eSEd Maste * Issue a warning if there are VMA/LMA adjust requests for 332a85fe12eSEd Maste * some nonexistent sections. 333a85fe12eSEd Maste */ 334a85fe12eSEd Maste if ((ecp->flags & NO_CHANGE_WARN) == 0) { 335a85fe12eSEd Maste STAILQ_FOREACH(sac, &ecp->v_sac, sac_list) { 336a85fe12eSEd Maste if (!sac->setvma && !sac->setlma && 337a85fe12eSEd Maste !sac->vma_adjust && !sac->lma_adjust) 338a85fe12eSEd Maste continue; 339a85fe12eSEd Maste found = 0; 340a85fe12eSEd Maste TAILQ_FOREACH(s, &ecp->v_sec, sec_list) { 341a85fe12eSEd Maste if (s->pseudo || s->name == NULL) 342a85fe12eSEd Maste continue; 343a85fe12eSEd Maste if (!strcmp(s->name, sac->name)) { 344a85fe12eSEd Maste found = 1; 345a85fe12eSEd Maste break; 346a85fe12eSEd Maste } 347a85fe12eSEd Maste } 348a85fe12eSEd Maste if (!found) 349a85fe12eSEd Maste warnx("cannot find section `%s'", sac->name); 350a85fe12eSEd Maste } 351a85fe12eSEd Maste } 352a85fe12eSEd Maste } 353a85fe12eSEd Maste 354a85fe12eSEd Maste static void 355a85fe12eSEd Maste insert_to_inseg_list(struct segment *seg, struct section *sec) 356a85fe12eSEd Maste { 357a85fe12eSEd Maste struct section *s; 358a85fe12eSEd Maste int i; 359a85fe12eSEd Maste 360a85fe12eSEd Maste seg->nsec++; 361a85fe12eSEd Maste seg->v_sec = realloc(seg->v_sec, seg->nsec * sizeof(*seg->v_sec)); 362a85fe12eSEd Maste if (seg->v_sec == NULL) 363a85fe12eSEd Maste err(EXIT_FAILURE, "realloc failed"); 364a85fe12eSEd Maste 365a85fe12eSEd Maste /* 366a85fe12eSEd Maste * Sort the section in order of offset. 367a85fe12eSEd Maste */ 368a85fe12eSEd Maste 369a85fe12eSEd Maste for (i = seg->nsec - 1; i > 0; i--) { 370a85fe12eSEd Maste s = seg->v_sec[i - 1]; 371a85fe12eSEd Maste if (sec->off >= s->off) { 372a85fe12eSEd Maste seg->v_sec[i] = sec; 373a85fe12eSEd Maste break; 374a85fe12eSEd Maste } else 375a85fe12eSEd Maste seg->v_sec[i] = s; 376a85fe12eSEd Maste } 377a85fe12eSEd Maste if (i == 0) 378a85fe12eSEd Maste seg->v_sec[0] = sec; 379a85fe12eSEd Maste } 380a85fe12eSEd Maste 381a85fe12eSEd Maste void 382a85fe12eSEd Maste setup_phdr(struct elfcopy *ecp) 383a85fe12eSEd Maste { 384a85fe12eSEd Maste struct segment *seg; 385a85fe12eSEd Maste GElf_Phdr iphdr; 386a85fe12eSEd Maste size_t iphnum; 387a85fe12eSEd Maste int i; 388a85fe12eSEd Maste 389a85fe12eSEd Maste if (elf_getphnum(ecp->ein, &iphnum) == 0) 390a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_getphnum failed: %s", 391a85fe12eSEd Maste elf_errmsg(-1)); 392a85fe12eSEd Maste 393a85fe12eSEd Maste ecp->ophnum = ecp->iphnum = iphnum; 394a85fe12eSEd Maste if (iphnum == 0) 395a85fe12eSEd Maste return; 396a85fe12eSEd Maste 397a85fe12eSEd Maste /* If --only-keep-debug is specified, discard all program headers. */ 398a85fe12eSEd Maste if (ecp->strip == STRIP_NONDEBUG) { 399a85fe12eSEd Maste ecp->ophnum = 0; 400a85fe12eSEd Maste return; 401a85fe12eSEd Maste } 402a85fe12eSEd Maste 403a85fe12eSEd Maste for (i = 0; (size_t)i < iphnum; i++) { 404a85fe12eSEd Maste if (gelf_getphdr(ecp->ein, i, &iphdr) != &iphdr) 405a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_getphdr failed: %s", 406a85fe12eSEd Maste elf_errmsg(-1)); 407a85fe12eSEd Maste if ((seg = calloc(1, sizeof(*seg))) == NULL) 408a85fe12eSEd Maste err(EXIT_FAILURE, "calloc failed"); 409a85fe12eSEd Maste seg->addr = iphdr.p_vaddr; 410a85fe12eSEd Maste seg->off = iphdr.p_offset; 411a85fe12eSEd Maste seg->fsz = iphdr.p_filesz; 412a85fe12eSEd Maste seg->msz = iphdr.p_memsz; 413a85fe12eSEd Maste seg->type = iphdr.p_type; 414a85fe12eSEd Maste STAILQ_INSERT_TAIL(&ecp->v_seg, seg, seg_list); 415a85fe12eSEd Maste } 416a85fe12eSEd Maste } 417a85fe12eSEd Maste 418a85fe12eSEd Maste void 419a85fe12eSEd Maste copy_phdr(struct elfcopy *ecp) 420a85fe12eSEd Maste { 421a85fe12eSEd Maste struct segment *seg; 422a85fe12eSEd Maste struct section *s; 423a85fe12eSEd Maste GElf_Phdr iphdr, ophdr; 424a85fe12eSEd Maste int i; 425a85fe12eSEd Maste 426a85fe12eSEd Maste STAILQ_FOREACH(seg, &ecp->v_seg, seg_list) { 427a85fe12eSEd Maste if (seg->type == PT_PHDR) { 428a85fe12eSEd Maste if (!TAILQ_EMPTY(&ecp->v_sec)) { 429a85fe12eSEd Maste s = TAILQ_FIRST(&ecp->v_sec); 430a85fe12eSEd Maste if (s->pseudo) 431a85fe12eSEd Maste seg->addr = s->lma + 432a85fe12eSEd Maste gelf_fsize(ecp->eout, ELF_T_EHDR, 433a85fe12eSEd Maste 1, EV_CURRENT); 434a85fe12eSEd Maste } 435a85fe12eSEd Maste seg->fsz = seg->msz = gelf_fsize(ecp->eout, ELF_T_PHDR, 436a85fe12eSEd Maste ecp->ophnum, EV_CURRENT); 437a85fe12eSEd Maste continue; 438a85fe12eSEd Maste } 439a85fe12eSEd Maste 440a85fe12eSEd Maste seg->fsz = seg->msz = 0; 441a85fe12eSEd Maste for (i = 0; i < seg->nsec; i++) { 442a85fe12eSEd Maste s = seg->v_sec[i]; 44330568ad3SEd Maste seg->msz = s->vma + s->sz - seg->addr; 444a85fe12eSEd Maste if (s->type != SHT_NOBITS) 445*b00fe64fSEd Maste seg->fsz = s->off + s->sz - seg->off; 446a85fe12eSEd Maste } 447a85fe12eSEd Maste } 448a85fe12eSEd Maste 449a85fe12eSEd Maste /* 450a85fe12eSEd Maste * Allocate space for program headers, note that libelf keep 451a85fe12eSEd Maste * track of the number in internal variable, and a call to 452a85fe12eSEd Maste * elf_update is needed to update e_phnum of ehdr. 453a85fe12eSEd Maste */ 454a85fe12eSEd Maste if (gelf_newphdr(ecp->eout, ecp->ophnum) == NULL) 455a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_newphdr() failed: %s", 456a85fe12eSEd Maste elf_errmsg(-1)); 457a85fe12eSEd Maste 458a85fe12eSEd Maste /* 459a85fe12eSEd Maste * This elf_update() call is to update the e_phnum field in 460a85fe12eSEd Maste * ehdr. It's necessary because later we will call gelf_getphdr(), 461a85fe12eSEd Maste * which does sanity check by comparing ndx argument with e_phnum. 462a85fe12eSEd Maste */ 463a85fe12eSEd Maste if (elf_update(ecp->eout, ELF_C_NULL) < 0) 464a85fe12eSEd Maste errx(EXIT_FAILURE, "elf_update() failed: %s", elf_errmsg(-1)); 465a85fe12eSEd Maste 466a85fe12eSEd Maste /* 467a85fe12eSEd Maste * iphnum == ophnum, since we don't remove program headers even if 468a85fe12eSEd Maste * they no longer contain sections. 469a85fe12eSEd Maste */ 470a85fe12eSEd Maste i = 0; 471a85fe12eSEd Maste STAILQ_FOREACH(seg, &ecp->v_seg, seg_list) { 472a85fe12eSEd Maste if (i >= ecp->iphnum) 473a85fe12eSEd Maste break; 474a85fe12eSEd Maste if (gelf_getphdr(ecp->ein, i, &iphdr) != &iphdr) 475a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_getphdr failed: %s", 476a85fe12eSEd Maste elf_errmsg(-1)); 477a85fe12eSEd Maste if (gelf_getphdr(ecp->eout, i, &ophdr) != &ophdr) 478a85fe12eSEd Maste errx(EXIT_FAILURE, "gelf_getphdr failed: %s", 479a85fe12eSEd Maste elf_errmsg(-1)); 480a85fe12eSEd Maste 481a85fe12eSEd Maste ophdr.p_type = iphdr.p_type; 482a85fe12eSEd Maste ophdr.p_vaddr = seg->addr; 483a85fe12eSEd Maste ophdr.p_paddr = seg->addr; 484a85fe12eSEd Maste ophdr.p_flags = iphdr.p_flags; 485a85fe12eSEd Maste ophdr.p_align = iphdr.p_align; 486a85fe12eSEd Maste ophdr.p_offset = seg->off; 487a85fe12eSEd Maste ophdr.p_filesz = seg->fsz; 488a85fe12eSEd Maste ophdr.p_memsz = seg->msz; 489a85fe12eSEd Maste if (!gelf_update_phdr(ecp->eout, i, &ophdr)) 490a85fe12eSEd Maste err(EXIT_FAILURE, "gelf_update_phdr failed :%s", 491a85fe12eSEd Maste elf_errmsg(-1)); 492a85fe12eSEd Maste 493a85fe12eSEd Maste i++; 494a85fe12eSEd Maste } 495a85fe12eSEd Maste } 496