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