1/* @LICENSE(UNSW_OZPLB) */ 2 3/* 4 * Australian Public Licence B (OZPLB) 5 * 6 * Version 1-0 7 * 8 * Copyright (c) 2004 University of New South Wales 9 * 10 * All rights reserved. 11 * 12 * Developed by: Operating Systems and Distributed Systems Group (DiSy) 13 * University of New South Wales 14 * http://www.disy.cse.unsw.edu.au 15 * 16 * Permission is granted by University of New South Wales, free of charge, to 17 * any person obtaining a copy of this software and any associated 18 * documentation files (the "Software") to deal with the Software without 19 * restriction, including (without limitation) the rights to use, copy, 20 * modify, adapt, merge, publish, distribute, communicate to the public, 21 * sublicense, and/or sell, lend or rent out copies of the Software, and 22 * to permit persons to whom the Software is furnished to do so, subject 23 * to the following conditions: 24 * 25 * * Redistributions of source code must retain the above copyright 26 * notice, this list of conditions and the following disclaimers. 27 * 28 * * Redistributions in binary form must reproduce the above 29 * copyright notice, this list of conditions and the following 30 * disclaimers in the documentation and/or other materials provided 31 * with the distribution. 32 * 33 * * Neither the name of University of New South Wales, nor the names of its 34 * contributors, may be used to endorse or promote products derived 35 * from this Software without specific prior written permission. 36 * 37 * EXCEPT AS EXPRESSLY STATED IN THIS LICENCE AND TO THE FULL EXTENT 38 * PERMITTED BY APPLICABLE LAW, THE SOFTWARE IS PROVIDED "AS-IS", AND 39 * NATIONAL ICT AUSTRALIA AND ITS CONTRIBUTORS MAKE NO REPRESENTATIONS, 40 * WARRANTIES OR CONDITIONS OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 41 * BUT NOT LIMITED TO ANY REPRESENTATIONS, WARRANTIES OR CONDITIONS 42 * REGARDING THE CONTENTS OR ACCURACY OF THE SOFTWARE, OR OF TITLE, 43 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, 44 * THE ABSENCE OF LATENT OR OTHER DEFECTS, OR THE PRESENCE OR ABSENCE OF 45 * ERRORS, WHETHER OR NOT DISCOVERABLE. 46 * 47 * TO THE FULL EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT SHALL 48 * NATIONAL ICT AUSTRALIA OR ITS CONTRIBUTORS BE LIABLE ON ANY LEGAL 49 * THEORY (INCLUDING, WITHOUT LIMITATION, IN AN ACTION OF CONTRACT, 50 * NEGLIGENCE OR OTHERWISE) FOR ANY CLAIM, LOSS, DAMAGES OR OTHER 51 * LIABILITY, INCLUDING (WITHOUT LIMITATION) LOSS OF PRODUCTION OR 52 * OPERATION TIME, LOSS, DAMAGE OR CORRUPTION OF DATA OR RECORDS; OR LOSS 53 * OF ANTICIPATED SAVINGS, OPPORTUNITY, REVENUE, PROFIT OR GOODWILL, OR 54 * OTHER ECONOMIC LOSS; OR ANY SPECIAL, INCIDENTAL, INDIRECT, 55 * CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES, ARISING OUT OF OR IN 56 * CONNECTION WITH THIS LICENCE, THE SOFTWARE OR THE USE OF OR OTHER 57 * DEALINGS WITH THE SOFTWARE, EVEN IF NATIONAL ICT AUSTRALIA OR ITS 58 * CONTRIBUTORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH CLAIM, LOSS, 59 * DAMAGES OR OTHER LIABILITY. 60 * 61 * If applicable legislation implies representations, warranties, or 62 * conditions, or imposes obligations or liability on University of New South 63 * Wales or one of its contributors in respect of the Software that 64 * cannot be wholly or partly excluded, restricted or modified, the 65 * liability of University of New South Wales or the contributor is limited, to 66 * the full extent permitted by the applicable legislation, at its 67 * option, to: 68 * a. in the case of goods, any one or more of the following: 69 * i. the replacement of the goods or the supply of equivalent goods; 70 * ii. the repair of the goods; 71 * iii. the payment of the cost of replacing the goods or of acquiring 72 * equivalent goods; 73 * iv. the payment of the cost of having the goods repaired; or 74 * b. in the case of services: 75 * i. the supplying of the services again; or 76 * ii. the payment of the cost of having the services supplied again. 77 * 78 * The construction, validity and performance of this licence is governed 79 * by the laws in force in New South Wales, Australia. 80 */ 81#include <elf/elf.h> 82#include <elf/elf32.h> 83#include <elf/elf64.h> 84#include <string.h> 85#include <stdio.h> 86 87/* ELF header functions */ 88int elf_newFile(void *file, size_t size, elf_t *res) 89{ 90 return elf_newFile_maybe_unsafe(file, size, true, true, res); 91} 92 93int elf_newFile_maybe_unsafe(void *file, size_t size, bool check_pht, bool check_st, elf_t *res) 94{ 95 elf_t new_file = { 96 .elfFile = file, 97 .elfSize = size 98 }; 99 100 int status = elf_checkFile(&new_file); 101 if (status < 0) { 102 return status; 103 } 104 105 if (check_pht) { 106 status = elf_checkProgramHeaderTable(&new_file); 107 if (status < 0) { 108 return status; 109 } 110 } 111 112 if (check_st) { 113 status = elf_checkSectionTable(&new_file); 114 if (status < 0) { 115 return status; 116 } 117 } 118 119 if (res) { 120 *res = new_file; 121 } 122 123 return status; 124} 125 126int elf_check_magic(char *file) 127{ 128 if (memcmp(file, ELFMAG, SELFMAG) != 0) { 129 return -1; 130 } 131 132 return 0; 133} 134 135/* 136 * Checks that elfFile points to a valid elf file. Returns 0 if the elf 137 * file is valid, < 0 if invalid. 138 */ 139int elf_checkFile(elf_t *elfFile) 140{ 141 int res = elf32_checkFile(elfFile); 142 if (res == 0) { 143 return 0; 144 } 145 146 res = elf64_checkFile(elfFile); 147 if (res == 0) { 148 return 0; 149 } 150 151 return -1; 152} 153 154int elf_checkProgramHeaderTable(elf_t *elfFile) 155{ 156 if (elf_isElf32(elfFile)) { 157 return elf32_checkProgramHeaderTable(elfFile); 158 } else { 159 return elf64_checkProgramHeaderTable(elfFile); 160 } 161} 162 163int elf_checkSectionTable(elf_t *elfFile) 164{ 165 if (elf_isElf32(elfFile)) { 166 return elf32_checkSectionTable(elfFile); 167 } else { 168 return elf64_checkSectionTable(elfFile); 169 } 170} 171 172uintptr_t elf_getEntryPoint(elf_t *elfFile) 173{ 174 if (elf_isElf32(elfFile)) { 175 return elf32_getEntryPoint(elfFile); 176 } else { 177 return elf64_getEntryPoint(elfFile); 178 } 179} 180 181size_t elf_getNumProgramHeaders(elf_t *elfFile) 182{ 183 if (elf_isElf32(elfFile)) { 184 return elf32_getNumProgramHeaders(elfFile); 185 } else { 186 return elf64_getNumProgramHeaders(elfFile); 187 } 188} 189 190size_t elf_getNumSections(elf_t *elfFile) 191{ 192 if (elf_isElf32(elfFile)) { 193 return elf32_getNumSections(elfFile); 194 } else { 195 return elf64_getNumSections(elfFile); 196 } 197} 198 199size_t elf_getSectionStringTableIndex(elf_t *elf) 200{ 201 if (elf_isElf32(elf)) { 202 return elf32_getSectionStringTableIndex(elf); 203 } else { 204 return elf64_getSectionStringTableIndex(elf); 205 } 206} 207 208const char *elf_getStringTable(elf_t *elf, size_t string_segment) 209{ 210 const char *string_table = elf_getSection(elf, string_segment); 211 if (string_table == NULL) { 212 return NULL; /* no such section */ 213 } 214 215 if (elf_getSectionType(elf, string_segment) != SHT_STRTAB) { 216 return NULL; /* not a string table */ 217 } 218 219 size_t size = elf_getSectionSize(elf, string_segment); 220 if (string_table[size - 1] != 0) { 221 return NULL; /* string table is not null-terminated */ 222 } 223 224 return string_table; 225} 226 227const char *elf_getSectionStringTable(elf_t *elf) 228{ 229 size_t index = elf_getSectionStringTableIndex(elf); 230 return elf_getStringTable(elf, index); 231} 232 233 234/* Section header functions */ 235void *elf_getSection(elf_t *elf, size_t i) 236{ 237 if (i == 0 || i >= elf_getNumSections(elf)) { 238 return NULL; /* no such section */ 239 } 240 241 size_t section_offset = elf_getSectionOffset(elf, i); 242 size_t section_size = elf_getSectionSize(elf, i); 243 if (section_size == 0) { 244 return NULL; /* section is empty */ 245 } 246 247 size_t section_end = section_offset + section_size; 248 /* possible wraparound - check that section end is not before section start */ 249 if (section_end > elf->elfSize || section_end < section_offset) { 250 return NULL; 251 } 252 253 return elf->elfFile + section_offset; 254} 255 256void *elf_getSectionNamed(elf_t *elfFile, const char *str, size_t *id) 257{ 258 size_t numSections = elf_getNumSections(elfFile); 259 for (size_t i = 0; i < numSections; i++) { 260 if (strcmp(str, elf_getSectionName(elfFile, i)) == 0) { 261 if (id != NULL) { 262 *id = i; 263 } 264 return elf_getSection(elfFile, i); 265 } 266 } 267 return NULL; 268} 269 270const char *elf_getSectionName(elf_t *elf, size_t i) 271{ 272 size_t str_table_idx = elf_getSectionStringTableIndex(elf); 273 const char *str_table = elf_getStringTable(elf, str_table_idx); 274 size_t offset = elf_getSectionNameOffset(elf, i); 275 size_t size = elf_getSectionSize(elf, str_table_idx); 276 277 if (str_table == NULL || offset > size) { 278 return "<corrupted>"; 279 } 280 281 return str_table + offset; 282} 283 284size_t elf_getSectionNameOffset(elf_t *elfFile, size_t i) 285{ 286 if (elf_isElf32(elfFile)) { 287 return elf32_getSectionNameOffset(elfFile, i); 288 } else { 289 return elf64_getSectionNameOffset(elfFile, i); 290 } 291} 292 293uint32_t elf_getSectionType(elf_t *elfFile, size_t i) 294{ 295 if (elf_isElf32(elfFile)) { 296 return elf32_getSectionType(elfFile, i); 297 } else { 298 return elf64_getSectionType(elfFile, i); 299 } 300} 301 302size_t elf_getSectionFlags(elf_t *elfFile, size_t i) 303{ 304 if (elf_isElf32(elfFile)) { 305 return elf32_getSectionFlags(elfFile, i); 306 } else { 307 return elf64_getSectionFlags(elfFile, i); 308 } 309} 310 311uintptr_t elf_getSectionAddr(elf_t *elfFile, size_t i) 312{ 313 if (elf_isElf32(elfFile)) { 314 return elf32_getSectionAddr(elfFile, i); 315 } else { 316 return elf64_getSectionAddr(elfFile, i); 317 } 318} 319 320size_t elf_getSectionOffset(elf_t *elfFile, size_t i) 321{ 322 if (elf_isElf32(elfFile)) { 323 return elf32_getSectionOffset(elfFile, i); 324 } else { 325 return elf64_getSectionOffset(elfFile, i); 326 } 327} 328 329size_t elf_getSectionSize(elf_t *elfFile, size_t i) 330{ 331 if (elf_isElf32(elfFile)) { 332 return elf32_getSectionSize(elfFile, i); 333 } else { 334 return elf64_getSectionSize(elfFile, i); 335 } 336} 337 338uint32_t elf_getSectionLink(elf_t *elfFile, size_t i) 339{ 340 if (elf_isElf32(elfFile)) { 341 return elf32_getSectionLink(elfFile, i); 342 } else { 343 return elf64_getSectionLink(elfFile, i); 344 } 345} 346 347uint32_t elf_getSectionInfo(elf_t *elfFile, size_t i) 348{ 349 if (elf_isElf32(elfFile)) { 350 return elf32_getSectionInfo(elfFile, i); 351 } else { 352 return elf64_getSectionInfo(elfFile, i); 353 } 354} 355 356size_t elf_getSectionAddrAlign(elf_t *elfFile, size_t i) 357{ 358 if (elf_isElf32(elfFile)) { 359 return elf32_getSectionAddrAlign(elfFile, i); 360 } else { 361 return elf64_getSectionAddrAlign(elfFile, i); 362 } 363} 364 365size_t elf_getSectionEntrySize(elf_t *elfFile, size_t i) 366{ 367 if (elf_isElf32(elfFile)) { 368 return elf32_getSectionEntrySize(elfFile, i); 369 } else { 370 return elf64_getSectionEntrySize(elfFile, i); 371 } 372} 373 374 375/* Program headers function */ 376void *elf_getProgramSegment(elf_t *elf, size_t ph) 377{ 378 size_t offset = elf_getProgramHeaderOffset(elf, ph); 379 size_t file_size = elf_getProgramHeaderFileSize(elf, ph); 380 size_t segment_end = offset + file_size; 381 /* possible wraparound - check that segment end is not before segment start */ 382 if (elf->elfSize < segment_end || segment_end < offset) { 383 return NULL; 384 } 385 386 return elf->elfFile + offset; 387} 388 389uint32_t elf_getProgramHeaderType(elf_t *elfFile, size_t ph) 390{ 391 if (elf_isElf32(elfFile)) { 392 return elf32_getProgramHeaderType(elfFile, ph); 393 } else { 394 return elf64_getProgramHeaderType(elfFile, ph); 395 } 396} 397 398size_t elf_getProgramHeaderOffset(elf_t *elfFile, size_t ph) 399{ 400 if (elf_isElf32(elfFile)) { 401 return elf32_getProgramHeaderOffset(elfFile, ph); 402 } else { 403 return elf64_getProgramHeaderOffset(elfFile, ph); 404 } 405} 406 407uintptr_t elf_getProgramHeaderVaddr(elf_t *elfFile, size_t ph) 408{ 409 if (elf_isElf32(elfFile)) { 410 return elf32_getProgramHeaderVaddr(elfFile, ph); 411 } else { 412 return elf64_getProgramHeaderVaddr(elfFile, ph); 413 } 414} 415 416uintptr_t elf_getProgramHeaderPaddr(elf_t *elfFile, size_t ph) 417{ 418 if (elf_isElf32(elfFile)) { 419 return elf32_getProgramHeaderPaddr(elfFile, ph); 420 } else { 421 return elf64_getProgramHeaderPaddr(elfFile, ph); 422 } 423} 424 425size_t elf_getProgramHeaderFileSize(elf_t *elfFile, size_t ph) 426{ 427 if (elf_isElf32(elfFile)) { 428 return elf32_getProgramHeaderFileSize(elfFile, ph); 429 } else { 430 return elf64_getProgramHeaderFileSize(elfFile, ph); 431 } 432} 433 434size_t elf_getProgramHeaderMemorySize(elf_t *elfFile, size_t ph) 435{ 436 if (elf_isElf32(elfFile)) { 437 return elf32_getProgramHeaderMemorySize(elfFile, ph); 438 } else { 439 return elf64_getProgramHeaderMemorySize(elfFile, ph); 440 } 441} 442 443uint32_t elf_getProgramHeaderFlags(elf_t *elfFile, size_t ph) 444{ 445 if (elf_isElf32(elfFile)) { 446 return elf32_getProgramHeaderFlags(elfFile, ph); 447 } else { 448 return elf64_getProgramHeaderFlags(elfFile, ph); 449 } 450} 451 452size_t elf_getProgramHeaderAlign(elf_t *elfFile, size_t ph) 453{ 454 if (elf_isElf32(elfFile)) { 455 return elf32_getProgramHeaderAlign(elfFile, ph); 456 } else { 457 return elf64_getProgramHeaderAlign(elfFile, ph); 458 } 459} 460 461 462/* Utility functions */ 463int elf_getMemoryBounds(elf_t *elfFile, elf_addr_type_t addr_type, uintptr_t *min, uintptr_t *max) 464{ 465 uintptr_t mem_min = UINTPTR_MAX; 466 uintptr_t mem_max = 0; 467 size_t i; 468 469 for (i = 0; i < elf_getNumProgramHeaders(elfFile); i++) { 470 uintptr_t sect_min, sect_max; 471 472 if (elf_getProgramHeaderMemorySize(elfFile, i) == 0) { 473 continue; 474 } 475 476 if (addr_type == PHYSICAL) { 477 sect_min = elf_getProgramHeaderPaddr(elfFile, i); 478 } else { 479 sect_min = elf_getProgramHeaderVaddr(elfFile, i); 480 } 481 482 sect_max = sect_min + elf_getProgramHeaderMemorySize(elfFile, i); 483 484 if (sect_max > mem_max) { 485 mem_max = sect_max; 486 } 487 if (sect_min < mem_min) { 488 mem_min = sect_min; 489 } 490 } 491 *min = mem_min; 492 *max = mem_max; 493 494 return 1; 495} 496 497int elf_vaddrInProgramHeader(elf_t *elfFile, size_t ph, uintptr_t vaddr) 498{ 499 uintptr_t min = elf_getProgramHeaderVaddr(elfFile, ph); 500 uintptr_t max = min + elf_getProgramHeaderMemorySize(elfFile, ph); 501 if (vaddr >= min && vaddr < max) { 502 return 1; 503 } else { 504 return 0; 505 } 506} 507 508uintptr_t elf_vtopProgramHeader(elf_t *elfFile, size_t ph, uintptr_t vaddr) 509{ 510 uintptr_t ph_phys = elf_getProgramHeaderPaddr(elfFile, ph); 511 uintptr_t ph_virt = elf_getProgramHeaderVaddr(elfFile, ph); 512 uintptr_t paddr; 513 514 paddr = vaddr - ph_virt + ph_phys; 515 516 return paddr; 517} 518 519int elf_loadFile(elf_t *elf, elf_addr_type_t addr_type) 520{ 521 size_t i; 522 523 for (i = 0; i < elf_getNumProgramHeaders(elf); i++) { 524 /* Load that section */ 525 uintptr_t dest, src; 526 size_t len; 527 if (addr_type == PHYSICAL) { 528 dest = elf_getProgramHeaderPaddr(elf, i); 529 } else { 530 dest = elf_getProgramHeaderVaddr(elf, i); 531 } 532 len = elf_getProgramHeaderFileSize(elf, i); 533 src = (uintptr_t) elf->elfFile + elf_getProgramHeaderOffset(elf, i); 534 memcpy((void *) dest, (void *) src, len); 535 dest += len; 536 memset((void *) dest, 0, elf_getProgramHeaderMemorySize(elf, i) - len); 537 } 538 539 return 1; 540} 541