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