1*839529caSEd Maste /*- 2*839529caSEd Maste * Copyright (c) 2016 Kai Wang 3*839529caSEd Maste * All rights reserved. 4*839529caSEd Maste * 5*839529caSEd Maste * Redistribution and use in source and binary forms, with or without 6*839529caSEd Maste * modification, are permitted provided that the following conditions 7*839529caSEd Maste * are met: 8*839529caSEd Maste * 1. Redistributions of source code must retain the above copyright 9*839529caSEd Maste * notice, this list of conditions and the following disclaimer. 10*839529caSEd Maste * 2. Redistributions in binary form must reproduce the above copyright 11*839529caSEd Maste * notice, this list of conditions and the following disclaimer in the 12*839529caSEd Maste * documentation and/or other materials provided with the distribution. 13*839529caSEd Maste * 14*839529caSEd Maste * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15*839529caSEd Maste * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16*839529caSEd Maste * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17*839529caSEd Maste * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18*839529caSEd Maste * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19*839529caSEd Maste * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20*839529caSEd Maste * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21*839529caSEd Maste * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22*839529caSEd Maste * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23*839529caSEd Maste * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24*839529caSEd Maste * SUCH DAMAGE. 25*839529caSEd Maste */ 26*839529caSEd Maste 27*839529caSEd Maste #include <errno.h> 28*839529caSEd Maste #include <string.h> 29*839529caSEd Maste 30*839529caSEd Maste #include "_libpe.h" 31*839529caSEd Maste 32*839529caSEd Maste ELFTC_VCSID("$Id: pe_section.c 3312 2016-01-10 09:23:51Z kaiwang27 $"); 33*839529caSEd Maste 34*839529caSEd Maste PE_Scn * 35*839529caSEd Maste pe_getscn(PE *pe, size_t ndx) 36*839529caSEd Maste { 37*839529caSEd Maste PE_Scn *ps; 38*839529caSEd Maste 39*839529caSEd Maste if (pe == NULL || ndx < 1 || ndx > 0xFFFFU) { 40*839529caSEd Maste errno = EINVAL; 41*839529caSEd Maste return (NULL); 42*839529caSEd Maste } 43*839529caSEd Maste 44*839529caSEd Maste STAILQ_FOREACH(ps, &pe->pe_scn, ps_next) { 45*839529caSEd Maste if (ps->ps_ndx == ndx) 46*839529caSEd Maste return (ps); 47*839529caSEd Maste } 48*839529caSEd Maste 49*839529caSEd Maste errno = ENOENT; 50*839529caSEd Maste 51*839529caSEd Maste return (NULL); 52*839529caSEd Maste } 53*839529caSEd Maste 54*839529caSEd Maste size_t 55*839529caSEd Maste pe_ndxscn(PE_Scn *ps) 56*839529caSEd Maste { 57*839529caSEd Maste 58*839529caSEd Maste if (ps == NULL) { 59*839529caSEd Maste errno = EINVAL; 60*839529caSEd Maste return (0); 61*839529caSEd Maste } 62*839529caSEd Maste 63*839529caSEd Maste return (ps->ps_ndx); 64*839529caSEd Maste } 65*839529caSEd Maste 66*839529caSEd Maste PE_Scn * 67*839529caSEd Maste pe_nextscn(PE *pe, PE_Scn *ps) 68*839529caSEd Maste { 69*839529caSEd Maste 70*839529caSEd Maste if (pe == NULL) { 71*839529caSEd Maste errno = EINVAL; 72*839529caSEd Maste return (NULL); 73*839529caSEd Maste } 74*839529caSEd Maste 75*839529caSEd Maste if (ps == NULL) 76*839529caSEd Maste ps = STAILQ_FIRST(&pe->pe_scn); 77*839529caSEd Maste else 78*839529caSEd Maste ps = STAILQ_NEXT(ps, ps_next); 79*839529caSEd Maste 80*839529caSEd Maste while (ps != NULL) { 81*839529caSEd Maste if (ps->ps_ndx >= 1 && ps->ps_ndx <= 0xFFFFU) 82*839529caSEd Maste return (ps); 83*839529caSEd Maste ps = STAILQ_NEXT(ps, ps_next); 84*839529caSEd Maste } 85*839529caSEd Maste 86*839529caSEd Maste return (NULL); 87*839529caSEd Maste } 88*839529caSEd Maste 89*839529caSEd Maste PE_Scn * 90*839529caSEd Maste pe_newscn(PE *pe) 91*839529caSEd Maste { 92*839529caSEd Maste PE_Scn *ps, *tps, *_tps; 93*839529caSEd Maste 94*839529caSEd Maste if (pe == NULL) { 95*839529caSEd Maste errno = EINVAL; 96*839529caSEd Maste return (NULL); 97*839529caSEd Maste } 98*839529caSEd Maste 99*839529caSEd Maste if (pe->pe_cmd == PE_C_READ || pe->pe_flags & LIBPE_F_FD_DONE) { 100*839529caSEd Maste errno = EACCES; 101*839529caSEd Maste return (NULL); 102*839529caSEd Maste } 103*839529caSEd Maste 104*839529caSEd Maste if ((ps = libpe_alloc_scn(pe)) == NULL) 105*839529caSEd Maste return (NULL); 106*839529caSEd Maste 107*839529caSEd Maste if (pe->pe_flags & LIBPE_F_BAD_SEC_HEADER) { 108*839529caSEd Maste STAILQ_FOREACH_SAFE(tps, &pe->pe_scn, ps_next, _tps) 109*839529caSEd Maste libpe_release_scn(tps); 110*839529caSEd Maste pe->pe_flags &= ~LIBPE_F_BAD_SEC_HEADER; 111*839529caSEd Maste } 112*839529caSEd Maste 113*839529caSEd Maste STAILQ_INSERT_TAIL(&pe->pe_scn, ps, ps_next); 114*839529caSEd Maste 115*839529caSEd Maste ps->ps_flags |= PE_F_DIRTY | LIBPE_F_LOAD_SECTION; 116*839529caSEd Maste pe->pe_flags |= LIBPE_F_DIRTY_SEC_HEADER; 117*839529caSEd Maste 118*839529caSEd Maste return (ps); 119*839529caSEd Maste } 120*839529caSEd Maste 121*839529caSEd Maste PE_Scn * 122*839529caSEd Maste pe_insertscn(PE *pe, size_t ndx) 123*839529caSEd Maste { 124*839529caSEd Maste PE_Scn *ps, *a, *b; 125*839529caSEd Maste 126*839529caSEd Maste if (pe == NULL || ndx < 1 || ndx > 0xFFFFU) { 127*839529caSEd Maste errno = EINVAL; 128*839529caSEd Maste return (NULL); 129*839529caSEd Maste } 130*839529caSEd Maste 131*839529caSEd Maste if (pe->pe_cmd == PE_C_READ || pe->pe_flags & LIBPE_F_FD_DONE) { 132*839529caSEd Maste errno = EACCES; 133*839529caSEd Maste return (NULL); 134*839529caSEd Maste } 135*839529caSEd Maste 136*839529caSEd Maste if ((ps = libpe_alloc_scn(pe)) == NULL) 137*839529caSEd Maste return (NULL); 138*839529caSEd Maste 139*839529caSEd Maste if (pe->pe_flags & LIBPE_F_BAD_SEC_HEADER) { 140*839529caSEd Maste STAILQ_FOREACH_SAFE(a, &pe->pe_scn, ps_next, b) 141*839529caSEd Maste libpe_release_scn(a); 142*839529caSEd Maste pe->pe_flags &= ~LIBPE_F_BAD_SEC_HEADER; 143*839529caSEd Maste } 144*839529caSEd Maste 145*839529caSEd Maste b = NULL; 146*839529caSEd Maste STAILQ_FOREACH(a, &pe->pe_scn, ps_next) { 147*839529caSEd Maste if (a->ps_ndx & 0xFFFF0000U) 148*839529caSEd Maste continue; 149*839529caSEd Maste if (a->ps_ndx == ndx) 150*839529caSEd Maste break; 151*839529caSEd Maste b = a; 152*839529caSEd Maste } 153*839529caSEd Maste 154*839529caSEd Maste if (a == NULL) { 155*839529caSEd Maste STAILQ_INSERT_TAIL(&pe->pe_scn, ps, ps_next); 156*839529caSEd Maste if (b == NULL) 157*839529caSEd Maste ps->ps_ndx = 1; 158*839529caSEd Maste else 159*839529caSEd Maste ps->ps_ndx = b->ps_ndx + 1; 160*839529caSEd Maste } else if (b == NULL) { 161*839529caSEd Maste STAILQ_INSERT_HEAD(&pe->pe_scn, ps, ps_next); 162*839529caSEd Maste ps->ps_ndx = 1; 163*839529caSEd Maste } else { 164*839529caSEd Maste STAILQ_INSERT_AFTER(&pe->pe_scn, b, ps, ps_next); 165*839529caSEd Maste ps->ps_ndx = ndx; 166*839529caSEd Maste } 167*839529caSEd Maste 168*839529caSEd Maste a = ps; 169*839529caSEd Maste while ((a = STAILQ_NEXT(a, ps_next)) != NULL) { 170*839529caSEd Maste if ((a->ps_ndx & 0xFFFF0000U) == 0) 171*839529caSEd Maste a->ps_ndx++; 172*839529caSEd Maste } 173*839529caSEd Maste 174*839529caSEd Maste ps->ps_flags |= PE_F_DIRTY | LIBPE_F_LOAD_SECTION; 175*839529caSEd Maste pe->pe_flags |= LIBPE_F_DIRTY_SEC_HEADER; 176*839529caSEd Maste 177*839529caSEd Maste return (ps); 178*839529caSEd Maste } 179*839529caSEd Maste 180*839529caSEd Maste PE_SecHdr * 181*839529caSEd Maste pe_section_header(PE_Scn *ps) 182*839529caSEd Maste { 183*839529caSEd Maste 184*839529caSEd Maste if (ps == NULL) { 185*839529caSEd Maste errno = EINVAL; 186*839529caSEd Maste return (NULL); 187*839529caSEd Maste } 188*839529caSEd Maste 189*839529caSEd Maste return (&ps->ps_sh); 190*839529caSEd Maste } 191*839529caSEd Maste 192*839529caSEd Maste int 193*839529caSEd Maste pe_update_section_header(PE_Scn *ps, PE_SecHdr *sh) 194*839529caSEd Maste { 195*839529caSEd Maste PE *pe; 196*839529caSEd Maste 197*839529caSEd Maste if (ps == NULL || sh == NULL) { 198*839529caSEd Maste errno = EINVAL; 199*839529caSEd Maste return (-1); 200*839529caSEd Maste } 201*839529caSEd Maste 202*839529caSEd Maste pe = ps->ps_pe; 203*839529caSEd Maste 204*839529caSEd Maste if (pe->pe_cmd == PE_C_READ || pe->pe_flags & LIBPE_F_FD_DONE) { 205*839529caSEd Maste errno = EACCES; 206*839529caSEd Maste return (-1); 207*839529caSEd Maste } 208*839529caSEd Maste 209*839529caSEd Maste ps->ps_sh = *sh; 210*839529caSEd Maste pe->pe_flags |= LIBPE_F_DIRTY_SEC_HEADER; 211*839529caSEd Maste 212*839529caSEd Maste return (0); 213*839529caSEd Maste } 214