Clean up more code

- Found some bugs in LLVM compiler-rt library
- The useless LIBC_STUBS package is now deleted
- Improve the overflow checking story even further
- Get chibicc tests working in MODE=dbg mode again
- The libc/isystem/ headers now have correctly named guards
This commit is contained in:
Justine Tunney 2023-06-18 00:55:09 -07:00
parent afc58a8b41
commit d7c79f43ef
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
294 changed files with 912 additions and 1208 deletions

View file

@ -4,30 +4,23 @@
#include "libc/elf/struct/phdr.h"
#include "libc/elf/struct/shdr.h"
#include "libc/elf/struct/sym.h"
#include "libc/runtime/ezmap.internal.h"
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
#ifdef COSMO
/*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § executable & linkable format
cosmopolitan § executable linkable format
*/
char *GetElfStringTable(const Elf64_Ehdr *, size_t);
char *GetElfStrs(const Elf64_Ehdr *, size_t, size_t *);
Elf64_Sym *GetElfSymbolTable(const Elf64_Ehdr *, size_t, Elf64_Xword *);
char *GetElfStringTable(const Elf64_Ehdr *, size_t, const char *);
Elf64_Sym *GetElfSymbolTable(const Elf64_Ehdr *, size_t, int, Elf64_Xword *);
bool IsElf64Binary(const Elf64_Ehdr *, size_t);
bool IsElfSymbolContent(const Elf64_Sym *);
Elf64_Phdr *GetElfSegmentHeaderAddress(const Elf64_Ehdr *, size_t, Elf64_Half);
Elf64_Phdr *GetElfProgramHeaderAddress(const Elf64_Ehdr *, size_t, Elf64_Half);
Elf64_Shdr *GetElfSectionHeaderAddress(const Elf64_Ehdr *, size_t, Elf64_Half);
void *GetElfSectionAddress(const Elf64_Ehdr *, size_t, const Elf64_Shdr *);
char *GetElfSectionNameStringTable(const Elf64_Ehdr *, size_t);
void GetElfVirtualAddressRange(const Elf64_Ehdr *, size_t, intptr_t *,
intptr_t *);
char *GetElfString(const Elf64_Ehdr *, size_t, const char *, Elf64_Word);
const char *GetElfSectionName(const Elf64_Ehdr *, size_t, Elf64_Shdr *);
Elf64_Sym *GetElfDynSymbolTable(const Elf64_Ehdr *, size_t, Elf64_Xword *);
char *GetElfDynStringTable(const Elf64_Ehdr *, size_t);
#endif /* COSMO */
COSMOPOLITAN_C_END_

View file

@ -27,7 +27,6 @@ LIBC_ELF_A_DIRECTDEPS = \
LIBC_INTRIN \
LIBC_NEXGEN32E \
LIBC_STR \
LIBC_STUBS
LIBC_ELF_A_DEPS := \
$(call uniq,$(foreach x,$(LIBC_ELF_A_DIRECTDEPS),$($(x))))

View file

@ -1,36 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/elf/def.h"
#include "libc/elf/elf.h"
#include "libc/str/str.h"
char *GetElfDynStringTable(const Elf64_Ehdr *elf, size_t mapsize) {
int i;
char *name;
Elf64_Shdr *shdr;
for (i = 0; i < elf->e_shnum; ++i) {
if ((shdr = GetElfSectionHeaderAddress(elf, mapsize, i)) &&
shdr->sh_type == SHT_STRTAB &&
(name = GetElfSectionName(elf, mapsize, shdr)) &&
!strcmp(name, ".dynstr")) {
return GetElfSectionAddress(elf, mapsize, shdr);
}
}
return 0;
}

View file

@ -1,35 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/elf/def.h"
#include "libc/elf/elf.h"
Elf64_Sym *GetElfDynSymbolTable(const Elf64_Ehdr *elf, size_t mapsize,
Elf64_Xword *out_count) {
int i;
Elf64_Shdr *shdr;
for (i = elf->e_shnum; i-- > 0;) {
if ((shdr = GetElfSectionHeaderAddress(elf, mapsize, i)) && //
shdr->sh_type == SHT_DYNSYM && //
shdr->sh_entsize == sizeof(Elf64_Sym)) {
if (out_count) *out_count = shdr->sh_size / sizeof(Elf64_Sym);
return GetElfSectionAddress(elf, mapsize, shdr);
}
}
return 0;
}

View file

@ -17,16 +17,25 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/elf/elf.h"
#include "libc/stdckdint.h"
#include "libc/elf/scalar.h"
#include "libc/elf/struct/phdr.h"
Elf64_Phdr *GetElfSegmentHeaderAddress(const Elf64_Ehdr *elf, //
/**
* Returns program header at `elf.phdr[i]`.
*
* @param elf points to the start of the executable image
* @param mapsize is the number of bytes past `elf` we can access
* @param i is the program header index, starting at zero
* @return program header pointer, or null on error
*/
Elf64_Phdr *GetElfProgramHeaderAddress(const Elf64_Ehdr *elf, //
size_t mapsize, //
Elf64_Half i) { //
uint64_t last, addr;
uint64_t off;
if (i >= elf->e_phnum) return 0;
if (ckd_add(&addr, (uintptr_t)elf, elf->e_phoff)) return 0;
if (ckd_add(&addr, addr, (unsigned)i * elf->e_phentsize)) return 0;
if (ckd_add(&last, addr, elf->e_phentsize)) return 0;
if (last > (uintptr_t)elf + mapsize) return 0;
return (Elf64_Phdr *)addr;
if (elf->e_phoff <= 0) return 0;
if (elf->e_phoff >= mapsize) return 0;
if (elf->e_phentsize < sizeof(Elf64_Phdr)) return 0;
if ((off = elf->e_phoff + (unsigned)i * elf->e_phentsize) > mapsize) return 0;
return (Elf64_Phdr *)((char *)elf + off);
}

View file

@ -19,14 +19,23 @@
#include "libc/elf/elf.h"
#include "libc/stdckdint.h"
// note: should not be used on bss section
/**
* Returns pointer to elf section file content.
*
* This function shouldn't be used on the bss section.
*
* @param elf points to the start of the executable image
* @param mapsize is the number of bytes past `elf` we can access
* @param shdr is from GetElfSectionHeaderAddress() and null-propagating
* @return pointer to content bytes, or null on error
*/
void *GetElfSectionAddress(const Elf64_Ehdr *elf, // validated
size_t mapsize, // validated
const Elf64_Shdr *shdr) { // foreign
uint64_t addr, last;
uint64_t last;
if (!shdr) return 0;
if (ckd_add(&addr, (uintptr_t)elf, shdr->sh_offset)) return 0;
if (ckd_add(&last, addr, shdr->sh_size)) return 0;
if (last > (uintptr_t)elf + mapsize) return 0;
return (void *)addr;
if (shdr->sh_size <= 0) return 0;
if (ckd_add(&last, shdr->sh_offset, shdr->sh_size)) return 0;
if (last > mapsize) return 0;
return (char *)elf + shdr->sh_offset;
}

View file

@ -17,16 +17,24 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/elf/elf.h"
#include "libc/stdckdint.h"
#include "libc/elf/struct/shdr.h"
/**
* Returns section header object at `elf.section[i]`.
*
* @param elf points to the start of the executable image
* @param mapsize is the number of bytes past `elf` we can access
* @param i is the section header index, starting at zero
* @return section header pointer, or null on error
*/
Elf64_Shdr *GetElfSectionHeaderAddress(const Elf64_Ehdr *elf, //
size_t mapsize, //
Elf64_Half i) { //
uint64_t addr, last;
uint64_t off;
if (i >= elf->e_shnum) return 0;
if (ckd_add(&addr, (uintptr_t)elf, elf->e_shoff)) return 0;
if (ckd_add(&addr, addr, (unsigned)i * elf->e_shentsize)) return 0;
if (ckd_add(&last, addr, elf->e_shentsize)) return 0;
if (last > (uintptr_t)elf + mapsize) return 0;
return (Elf64_Shdr *)addr;
if (elf->e_shoff <= 0) return 0;
if (elf->e_shoff >= mapsize) return 0;
if (elf->e_shentsize < sizeof(Elf64_Shdr)) return 0;
if ((off = elf->e_shoff + (unsigned)i * elf->e_shentsize) > mapsize) return 0;
return (Elf64_Shdr *)((char *)elf + off);
}

View file

@ -17,9 +17,16 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/elf/elf.h"
#include "libc/elf/struct/shdr.h"
/**
* Returns section name string table.
*
* @param elf points to the start of the executable image
* @param mapsize is the number of bytes past `elf` we can access
* @return double-nul terminated string list, or null on error
*/
char *GetElfSectionNameStringTable(const Elf64_Ehdr *elf, size_t mapsize) {
if (!elf->e_shoff || !elf->e_shentsize) return 0;
return GetElfSectionAddress(
elf, mapsize, GetElfSectionHeaderAddress(elf, mapsize, elf->e_shstrndx));
}

View file

@ -17,17 +17,28 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/elf/elf.h"
#include "libc/stdckdint.h"
#include "libc/elf/scalar.h"
#include "libc/elf/struct/ehdr.h"
#include "libc/str/str.h"
/**
* Returns `strtab + i` from elf string table.
*
* @param elf points to the start of the executable image
* @param mapsize is the number of bytes past `elf` we can access
* @param strtab is double-nul string list from GetElfStringTable()
* @param i is byte index into strtab where needed string starts
* @return pointer to nul terminated string, or null on error
*/
char *GetElfString(const Elf64_Ehdr *elf, // validated
size_t mapsize, // validated
const char *strtab, // validated
Elf64_Word rva) { // foreign
uintptr_t addr;
if (!strtab) return 0;
if (ckd_add(&addr, (uintptr_t)strtab, rva)) return 0;
if (addr >= (uintptr_t)elf + mapsize) return 0;
if (!memchr((char *)addr, 0, (uintptr_t)elf + mapsize - addr)) return 0;
return (char *)addr;
Elf64_Word i) { // foreign
const char *e;
e = (const char *)elf;
if (strtab < e) return 0;
if (strtab >= e + mapsize) return 0;
if (strtab + i >= e + mapsize) return 0;
if (!memchr(strtab + i, 0, (e + mapsize) - (strtab + i))) return 0;
return (char *)strtab + i;
}

View file

@ -18,9 +18,21 @@
*/
#include "libc/elf/def.h"
#include "libc/elf/elf.h"
#include "libc/elf/struct/ehdr.h"
#include "libc/elf/struct/shdr.h"
#include "libc/str/str.h"
char *GetElfStringTable(const Elf64_Ehdr *elf, size_t mapsize) {
/**
* Returns pointer to elf string table.
*
* @param elf points to the start of the executable image
* @param mapsize is the number of bytes past `elf` we can access
* @param section_name is usually `".strtab"`, `".dynstr"`, or null
* @return pointer to double-nul terminated string list or null on error
*/
char *GetElfStringTable(const Elf64_Ehdr *elf, //
size_t mapsize, //
const char *section_name) {
int i;
char *name;
Elf64_Shdr *shdr;
@ -28,9 +40,9 @@ char *GetElfStringTable(const Elf64_Ehdr *elf, size_t mapsize) {
if ((shdr = GetElfSectionHeaderAddress(elf, mapsize, i)) &&
shdr->sh_type == SHT_STRTAB &&
(name = GetElfSectionName(elf, mapsize, shdr)) &&
!strcmp(name, ".strtab")) {
(!section_name || !strcmp(name, section_name))) {
return GetElfSectionAddress(elf, mapsize, shdr);
}
}
return NULL;
return 0;
}

View file

@ -1,37 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/elf/def.h"
#include "libc/elf/elf.h"
#include "libc/str/str.h"
char *GetElfStrs(const Elf64_Ehdr *elf, size_t mapsize, size_t *out_size) {
int i;
char *name;
Elf64_Shdr *shdr;
for (i = 0; i < elf->e_shnum; ++i) {
if ((shdr = GetElfSectionHeaderAddress(elf, mapsize, i)) &&
shdr->sh_type == SHT_STRTAB &&
(name = GetElfSectionName(elf, mapsize, shdr)) &&
!strcmp(name, ".strtab")) {
if (out_size) *out_size = shdr->sh_size;
return GetElfSectionAddress(elf, mapsize, shdr);
}
}
return 0;
}

View file

@ -18,20 +18,32 @@
*/
#include "libc/elf/def.h"
#include "libc/elf/elf.h"
#include "libc/elf/scalar.h"
#include "libc/elf/struct/ehdr.h"
#include "libc/elf/struct/sym.h"
Elf64_Sym *GetElfSymbolTable(const Elf64_Ehdr *elf, size_t mapsize,
/**
* Returns pointer to elf symbol table.
*
* @param elf points to the start of the executable image
* @param mapsize is the number of bytes past `elf` we can access
* @param section_type is usually `SHT_SYMTAB` or `SHT_DYNSYM`
* @param out_count optionally receives number of elements in res
* @return pointer to symbol array, or null on error
*/
Elf64_Sym *GetElfSymbolTable(const Elf64_Ehdr *elf, //
size_t mapsize, //
int section_type, //
Elf64_Xword *out_count) {
int i;
Elf64_Shdr *shdr;
if (elf->e_shentsize) {
for (i = elf->e_shnum; i > 0; --i) {
shdr = GetElfSectionHeaderAddress(elf, mapsize, i - 1);
if (shdr->sh_type == SHT_SYMTAB) {
if (shdr->sh_entsize != sizeof(Elf64_Sym)) __builtin_trap();
if (out_count) *out_count = shdr->sh_size / sizeof(Elf64_Sym);
return GetElfSectionAddress(elf, mapsize, shdr);
}
for (i = elf->e_shnum; i > 0; --i) {
if ((shdr = GetElfSectionHeaderAddress(elf, mapsize, i - 1)) && //
shdr->sh_entsize == sizeof(Elf64_Sym) && //
shdr->sh_type == section_type) {
if (out_count) *out_count = shdr->sh_size / sizeof(Elf64_Sym);
return GetElfSectionAddress(elf, mapsize, shdr);
}
}
return NULL;
return 0;
}

View file

@ -1,39 +0,0 @@
/*-*- mode:c;indent-tabs-mode:nil;c-basic-offset:2;tab-width:8;coding:utf-8 -*-│
vi: set net ft=c ts=2 sts=2 sw=2 fenc=utf-8 :vi
Copyright 2020 Justine Alexandra Roberts Tunney
Permission to use, copy, modify, and/or distribute this software for
any purpose with or without fee is hereby granted, provided that the
above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/elf/elf.h"
#include "libc/limits.h"
void GetElfVirtualAddressRange(const Elf64_Ehdr *elf, size_t elfsize,
intptr_t *out_start, intptr_t *out_end) {
unsigned i;
Elf64_Phdr *phdr;
intptr_t start, end, pstart, pend;
start = INTPTR_MAX;
end = 0;
for (i = 0; i < elf->e_phnum; ++i) {
phdr = GetElfSegmentHeaderAddress(elf, elfsize, i);
if (phdr->p_type != PT_LOAD) continue;
pstart = phdr->p_vaddr;
pend = phdr->p_vaddr + phdr->p_memsz;
if (pstart < start) start = pstart;
if (pend > end) end = pend;
}
if (out_start) *out_start = start;
if (out_end) *out_end = end;
}

View file

@ -16,12 +16,20 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/elf/def.h"
#include "libc/elf/elf.h"
#include "libc/str/str.h"
#include "libc/elf/struct/ehdr.h"
#include "libc/intrin/bits.h"
/**
* Returns true if `elf` is a 64-bit elf executable.
*
* @param elf points to the start of the executable image
* @param mapsize is the number of bytes past `elf` we can access
* @return true if elf header looks legit
*/
bool IsElf64Binary(const Elf64_Ehdr *elf, size_t mapsize) {
if (mapsize < sizeof(Elf64_Ehdr)) return false;
if (memcmp(elf->e_ident, ELFMAG, 4)) return false;
return (elf->e_ident[EI_CLASS] == ELFCLASSNONE ||
elf->e_ident[EI_CLASS] == ELFCLASS64);
if (READ32LE(elf->e_ident) != READ32LE(ELFMAG)) return false;
return elf->e_ident[EI_CLASS] != ELFCLASS32;
}

View file

@ -1,6 +1,5 @@
#ifndef COSMOPOLITAN_LIBC_ELF_SCALAR_H_
#define COSMOPOLITAN_LIBC_ELF_SCALAR_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
#define Elf64_Addr uint64_t
#define Elf64_Half uint16_t
@ -13,5 +12,4 @@
#define Elf64_Xword uint64_t
#define Elf_Symndx uint32_t
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_ELF_SCALAR_H_ */