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