Make minor improvements

- Work towards simplifying ape.S startup process
- Rewrote ar because it took minutes to build cosmopolitan.a
main
Justine Tunney 2020-11-09 15:41:11 -08:00
parent 95bc650be8
commit aea89fe832
70 changed files with 1037 additions and 456 deletions

166
ape/ape.S
View File

@ -175,7 +175,7 @@ stub: mov $0x40,%dl # *literally* dos
built the last forty years these routines also canonicalize the built the last forty years these routines also canonicalize the
cpu and program state, as it is written in the System V ABI. */ cpu and program state, as it is written in the System V ABI. */
/ Initializes program and jumps to long mode loader. / Initializes program and jumps to real mode loader.
/ /
/ @param dl drive number (use 0x40 to skip bios disk load) / @param dl drive number (use 0x40 to skip bios disk load)
/ @mode real / @mode real
@ -188,62 +188,46 @@ pc: cld
#endif #endif
mov $REAL_STACK_FRAME>>4,%di # we need a stack mov $REAL_STACK_FRAME>>4,%di # we need a stack
xor %cx,%cx xor %cx,%cx
mov %cx,%es
rlstack %di,%cx rlstack %di,%cx
movpp %cs,%ax # memcpy() [relocate this page] push %cs # memcpy() [relocate this page]
pop %ds
call 1f call 1f
1: pop %si 1: pop %si
sub $RVA(1b),%si sub $RVA(1b),%si
mov $4,%cl mov $IMAGE_BASE_REAL>>4,%ax
1: shr %si push %ax # save real base
loop 1b push %ax
mov $512,%cx pop %es
mov $IMAGE_BASE_REAL>>4,%di
mov %si,%ds
mov %di,%es
xor %si,%si
xor %di,%di xor %di,%di
rep mov $512,%cx
movsb %ds:(%si),%es:(%di) rep movsb
#if USE_SYMBOL_HACK #if USE_SYMBOL_HACK
.byte 0x0f,0x1f,0207 # nop rdi binbase .byte 0x0f,0x1f,0207 # nop rdi binbase
.short (IMAGE_BASE_REAL-0x7c00)/512 .short (IMAGE_BASE_REAL-0x7c00)/512
#endif #endif
ljmp $0,$REAL(1f) # longjmp() ljmp $0,$REAL(1f) # longjmp()
1: mov $-512,%cx # memcpy() [relocate this frame] 1: mov %cx,%ds # %ds and %cs are now zero
rep mov $XLM_SIZE,%cx # memset to clear real bss
movsb %ds:(%si),%es:(%di)
xor %bp,%bp
mov %bp,%ds # %ds and %cs are now zero
call 1f # setup frame pointers
1: push %bp
mov %sp,%bp
mov $XLM_SIZE,%cx # memset() [clear real bss]
mov $XLM_BASE_REAL>>4,%ax mov $XLM_BASE_REAL>>4,%ax
mov %ax,%es mov %ax,%es
xor %ax,%ax xor %ax,%ax
xor %di,%di xor %di,%di
rep rep stosb
stosb %al,%es:(%di)
cmp $0x40,%dl # statfs() [disk geometry] cmp $0x40,%dl # statfs() [disk geometry]
je 6f je 6f
call dsknfo call dsknfo
mov $IMAGE_BASE_REAL>>4,%ax pop %es # restore real base
mov %ax,%es mov $1,%al # current sector
mov $v_ape_realsectors,%di # total sectors to read xor %cx,%cx # current cylinder
xor %dh,%dh # current head state xor %dh,%dh # current head
xor %cx,%cx # current cylinder state mov $v_ape_realsectors,%di # total sectors
3: mov %di,%ax 3: call pcread
call pcread
mov %es,%si
4: add $512>>4,%si
dec %di dec %di
jz 6f jnz 3b
dec %ax 6: mov %ax,XLM(LOADSTATE)+0
jnz 4b mov %cx,XLM(LOADSTATE)+2
mov %si,%es mov %dx,XLM(LOADSTATE)+4
jmp 3b
6: mov %cx,XLM(LOADSTATE)+0
mov %dx,XLM(LOADSTATE)+2
ljmp $0,$REAL(realmodeloader) ljmp $0,$REAL(realmodeloader)
.endfn pc,globl,hidden .endfn pc,globl,hidden
@ -334,66 +318,40 @@ dsknfo: push %bx
jmp 1b jmp 1b
.endfn dsknfo .endfn dsknfo
/ Reads disk sectors via BIOS. / Reads disk sector via BIOS.
/ /
/ Each call to this function performs a single read. It has a / @param al sector number
/ special ABI, where its parameters are preserved, and rolled
/ forward accordingly across calls. BIOS requirements on read
/ parameter validity are abstracted. If the requested size is
/ too large for one read, then it's tuned down appropriately.
/
/ Please note that dskinfo() must be called beforehand.
/
/ @param ax number sectors to read
/ @param es destination memory address >> 4 / @param es destination memory address >> 4
/ @param cx cylinder number / @param cx cylinder number
/ @param dh head number / @param dh head number
/ @param dl drive number / @param dl drive number
/ @return number of sectors actually read / @return number of sectors actually read
pcread: push %bx pcread: push %ax
xor %bx,%bx
mov XLM(DRIVE_LAST_SECTOR),%bl
cmp %ax,%bx # ax = min(ax, pertrack)
ja 1f
mov %bx,%ax
1: push %cx # how many sectors until 64k
push %ax # boundary reads can't cross
mov $0x1000,%bx # canonicalizing the segment
mov %es,%ax # register is not sufficient
sub %ax,%bx
and $0x0fff,%bx
mov $5,%cx
0: shr %bx
loop 0b
pop %ax
pop %cx
test %bx,%bx # %es 64k-aligned edge case
jz 1f
cmp %ax,%bx # ax = min(ax, remain64k)
ja 1f
mov %bx,%ax
1: push %ax # setup int-13-2() params
push %cx push %cx
xchg %cl,%ch xchg %cl,%ch
ror %cl ror %cl
ror %cl ror %cl
or $1,%cl # one cylinder at a time or %al,%cl
xor %bx,%bx # es:bx is destination addr xor %bx,%bx # es:bx is destination addr
mov $0x02,%ah # read disk sectors ordinal mov $1,%al # read only one disk sector
mov $2,%ah # read disk sectors ordinal
int $0x13 int $0x13
pop %cx pop %cx
pop %bx pop %ax
jc 9f jc 9f
mov $0,%ah mov %es,%si
cmp %ax,%bx add $512>>4,%si
jl 9f mov %si,%es
inc %al
cmp XLM(DRIVE_LAST_SECTOR),%al
jbe 2f
mov $1,%al
inc %cx inc %cx
cmp XLM(DRIVE_LAST_CYLINDER),%cx cmp XLM(DRIVE_LAST_CYLINDER),%cx
jle 2f jbe 2f
xor %cx,%cx xor %cx,%cx
inc %dh inc %dh
2: pop %bx 2: ret
ret
9: push %ax 9: push %ax
xor %ax,%ax # try disk reset on error xor %ax,%ax # try disk reset on error
int $0x13 int $0x13
@ -824,11 +782,11 @@ ape.pe: .ascin "PE",4
.long 0 # Checksum .long 0 # Checksum
.short v_ntsubsystem # Subsystem: 0=Neutral,2=GUI,3=Console .short v_ntsubsystem # Subsystem: 0=Neutral,2=GUI,3=Console
.short .LDLLEXE # DllCharacteristics .short .LDLLEXE # DllCharacteristics
.quad 0x0000000000100000 # StackReserve .quad 0x0000000000080000 # StackReserve
.quad 0x0000000000100000 # StackCommit .quad 0x0000000000080000 # StackCommit
.quad 0x0000000000000000 # HeapReserve .quad 0 # HeapReserve
.quad 0x0000000000000000 # HeapCommit .quad 0 # HeapCommit
.long 0x00000000 # LoaderFlags .long 0 # LoaderFlags
.long 16 # NumberOfDirectoryEntries .long 16 # NumberOfDirectoryEntries
.long 0,0 # ExportsDirectory .long 0,0 # ExportsDirectory
.long RVA(idata.idt) # ImportsDirectory .long RVA(idata.idt) # ImportsDirectory
@ -857,10 +815,10 @@ ape.pe: .ascin "PE",4
.stub .Lape.text.rva,long # Relative Virtual Address .stub .Lape.text.rva,long # Relative Virtual Address
.stub .Lape.text.filesz,long # Physical Size .stub .Lape.text.filesz,long # Physical Size
.stub .Lape.text.offset,long # Physical Offset .stub .Lape.text.offset,long # Physical Offset
.long 0x00000000 # Relocation Table Offset .long 0 # Relocation Table Offset
.long 0x00000000 # Line Number Table Offset .long 0 # Line Number Table Offset
.short 0x0000 # Relocation Count .short 0 # Relocation Count
.short 0x0000 # Line Number Count .short 0 # Line Number Count
.long .LPETEXT # Flags .long .LPETEXT # Flags
.previous .previous
@ -870,10 +828,10 @@ ape.pe: .ascin "PE",4
.stub .Lape.ram.rva,long # Relative Virtual Address .stub .Lape.ram.rva,long # Relative Virtual Address
.stub .Lape.ram.filesz,long # Physical Size .stub .Lape.ram.filesz,long # Physical Size
.stub .Lape.ram.offset,long # Physical Offset .stub .Lape.ram.offset,long # Physical Offset
.long 0x00000000 # Relocation Table Offset .long 0 # Relocation Table Offset
.long 0x00000000 # Line Number Table Offset .long 0 # Line Number Table Offset
.short 0x0000 # Relocation Count .short 0 # Relocation Count
.short 0x0000 # Line Number Count .short 0 # Line Number Count
.long .LPEDATA # Flags .long .LPEDATA # Flags
.previous .previous
@ -1246,7 +1204,8 @@ sflush: mov %si,%cx
mov $UART_TTYIDL,%ah mov $UART_TTYIDL,%ah
1: in %dx,%al 1: in %dx,%al
and %ah,%al and %ah,%al
rep nop # todo(jart): interrupts are better rep
nop
jz 1b jz 1b
loop 0b loop 0b
2: ret 2: ret
@ -1269,7 +1228,8 @@ sputc: push %ax
1: in %dx,%al 1: in %dx,%al
and %ah,%al and %ah,%al
jnz 2f jnz 2f
rep nop # todo(jart): interrupts are better rep
nop
jmp 1b jmp 1b
2: mov %di,%ax 2: mov %di,%ax
mov %si,%dx mov %si,%dx
@ -1356,7 +1316,7 @@ longmodeloader:
call e820 call e820
jc 9f jc 9f
call unreal call unreal
call hiload / call hiload
jmp golong jmp golong
9: mov $REAL(.Lstr.e820),%ax 9: mov $REAL(.Lstr.e820),%ax
call rldie call rldie
@ -1478,8 +1438,9 @@ hiload: push %bx
mov $v_ape_highsectors,%di # then copy rest off disk mov $v_ape_highsectors,%di # then copy rest off disk
mov $REAL_SCRATCH_AREA>>4,%ax # to real memory buffer mov $REAL_SCRATCH_AREA>>4,%ax # to real memory buffer
mov %ax,%es mov %ax,%es
mov XLM(LOADSTATE)+0,%cx mov XLM(LOADSTATE)+0,%ax
mov XLM(LOADSTATE)+2,%dx mov XLM(LOADSTATE)+2,%cx
mov XLM(LOADSTATE)+4,%dx
0: test %di,%di 0: test %di,%di
jz 9f jz 9f
mov %di,%ax mov %di,%ax
@ -1590,6 +1551,7 @@ pinit: push %ds
add $0x1000,%eax add $0x1000,%eax
add $8,%si add $8,%si
loop 0b loop 0b
movb $0,0 # unmap null
pop %ds pop %ds
movl $TIP-0x4000,XLM(PAGE_TABLE_STACK_POINTER) # STACKXLM movl $TIP-0x4000,XLM(PAGE_TABLE_STACK_POINTER) # STACKXLM
mov $TIP-0x1000,%eax # PML4TCR3 mov $TIP-0x1000,%eax # PML4TCR3
@ -1631,13 +1593,13 @@ long: push $GDT_LONG_DATA
xor %ebp,%ebp xor %ebp,%ebp
mov $REAL_STACK_FRAME+FRAMESIZE,%esp mov $REAL_STACK_FRAME+FRAMESIZE,%esp
call __map_image call __map_image
ezlea _metal,ax ezlea metal,ax
jmp *%rax jmp *%rax
.endfn long .endfn long
/ Long mode in virtual address space. / Long mode in virtual address space.
/ @noreturn / @noreturn
_metal: metal:
#if USE_SYMBOL_HACK #if USE_SYMBOL_HACK
.byte 0x0f,0x1f,0207 # nop rdi binbase .byte 0x0f,0x1f,0207 # nop rdi binbase
.long (IMAGE_BASE_VIRTUAL-IMAGE_BASE_REAL)/512 .long (IMAGE_BASE_VIRTUAL-IMAGE_BASE_REAL)/512
@ -1658,7 +1620,7 @@ _metal:
push $0 # argc push $0 # argc
xor %edi,%edi xor %edi,%edi
jmp _start jmp _start
.endfn _metal .endfn metal
/ Avoid linker script variables appearing as code in objdump. / Avoid linker script variables appearing as code in objdump.
.macro .ldsvar name:req .macro .ldsvar name:req

View File

@ -537,7 +537,8 @@ HIDDEN(.Lape.bss.align = .Lape.data.align);
/* Program Loader Auto-Tune */ /* Program Loader Auto-Tune */
HIDDEN(v_ape_realsectors = HIDDEN(v_ape_realsectors =
MIN(REAL_SCRATCH_AREA - IMAGE_BASE_REAL, MIN(REAL_SCRATCH_AREA - IMAGE_BASE_REAL,
ROUNDUP(RVA(_edata), 512)) / 512); ROUNDUP(RVA(_edata), 4096)) / 512);
HIDDEN(v_ape_realpages = v_ape_realsectors / (4096 / 512));
HIDDEN(v_ape_highsectors = HIDDEN(v_ape_highsectors =
(ROUNDUP(RVA(_edata), 512) / 512) - v_ape_realsectors); (ROUNDUP(RVA(_edata), 512) / 512) - v_ape_realsectors);

View File

@ -126,7 +126,7 @@
#define XLM_BADIDT 0x2230 #define XLM_BADIDT 0x2230
#define XLM_BADIDT_SIZE 6 #define XLM_BADIDT_SIZE 6
#define XLM_LOADSTATE 0x2240 #define XLM_LOADSTATE 0x2240
#define XLM_LOADSTATE_SIZE 4 #define XLM_LOADSTATE_SIZE 6
#define XLM_SIZE ROUNDUP(XLM_LOADSTATE + XLM_LOADSTATE_SIZE, 0x1000) #define XLM_SIZE ROUNDUP(XLM_LOADSTATE + XLM_LOADSTATE_SIZE, 0x1000)
#define IMAGE_BASE_REAL (XLM_BASE_REAL + XLM_SIZE) #define IMAGE_BASE_REAL (XLM_BASE_REAL + XLM_SIZE)

View File

@ -25,12 +25,11 @@ textreal static void __map_segment(uint64_t k, uint64_t a, uint64_t b) {
uint64_t *e; uint64_t *e;
for (; a < b; a += 0x1000) { for (; a < b; a += 0x1000) {
e = getpagetableentry(IMAGE_BASE_VIRTUAL + a, 3, &g_pml4t, &g_ptsp_xlm); e = getpagetableentry(IMAGE_BASE_VIRTUAL + a, 3, &g_pml4t, &g_ptsp_xlm);
*e = (IMAGE_BASE_PHYSICAL + a) | k; *e = (IMAGE_BASE_REAL + a) | k;
} }
} }
textreal void __map_image(void) { textreal void __map_image(void) {
pageunmap(0);
__map_segment(PAGE_V | PAGE_U, 0, (uintptr_t)_etext - IMAGE_BASE_VIRTUAL); __map_segment(PAGE_V | PAGE_U, 0, (uintptr_t)_etext - IMAGE_BASE_VIRTUAL);
__map_segment(PAGE_V | PAGE_U | PAGE_RW | PAGE_XD, __map_segment(PAGE_V | PAGE_U | PAGE_RW | PAGE_XD,
(uintptr_t)_etext - IMAGE_BASE_VIRTUAL, (uintptr_t)_etext - IMAGE_BASE_VIRTUAL,

View File

@ -4,57 +4,28 @@
# #
# OVERVIEW # OVERVIEW
# #
# GNU Archiver Veneer # Cosmopolitan Archiver
# #
# DESCRIPTION # DESCRIPTION
# #
# This script wraps normal archive commands that're transparently # This goes 100x faster than ar and ranlib.
# passed-through. It adds value too, by addressing difficulties
# that would normally cause a developer to need `make clean`.
# #
# EXAMPLE # EXAMPLE
# #
# build/archive ar rcsD library.a foo.o ... # build/archive rcsD library.a foo.o ...
if [ ! -d o/third_party/gcc ]; then
third_party/gcc/unbundle.sh
fi
export LC_ALL=C
RM=${RM:-$(command -v rm) -f} || exit
MKDIR=${MKDIR:-$(command -v mkdir) -p} || exit MKDIR=${MKDIR:-$(command -v mkdir) -p} || exit
# if [ -x "o/$MODE/tool/build/ar.com" ]; then
AR=$1 # set -- "o/$MODE/tool/build/ar.com" "$@"
ARFLAGS=$2 # else
OUT=$3 if [ ! -x o/build/bootstrap/ar.com ]; then
shift 3 mkdir -p o/build/bootstrap &&
cp -f build/bootstrap/ar.com o/build/bootstrap/ar.com.$$ &&
# remove directory arguments (having .a targets depend on dirs is what mv -f o/build/bootstrap/ar.com.$$ o/build/bootstrap/ar.com || exit
# lets them be invalidated by deleted files)
FIRST=1
for x; do
if [ $FIRST -eq 1 ]; then
set --
FIRST=0
fi
if [ -d "$x" ]; then
if [ -f "$OUT" ] && [ "$x" -nt "$OUT" ]; then
$RM "$OUT"
fi
continue
fi
if [ "$x" != "${x%.o}" ]; then
set -- "$@" "$x"
fi
done
set -- "$AR" "$ARFLAGS" "$OUT" "$@"
printf %s\\n "$*" >"$OUT.cmd"
OUTDIR="${OUT%/*}"
if [ "$OUTDIR" != "$OUT" ] && [ ! -d "$OUTDIR" ]; then
$MKDIR "$OUTDIR" || exit 2
fi fi
set -- o/build/bootstrap/ar.com "$@"
# fi
OUT=$3
printf "$LOGFMT" "${ACTION:-ARCHIVE.a}" "$OUT" >&2 printf "$LOGFMT" "${ACTION:-ARCHIVE.a}" "$OUT" >&2
# if [ "$SILENT" = "0" ]; then # if [ "$SILENT" = "0" ]; then

Binary file not shown.

View File

@ -65,7 +65,7 @@ CC = o/third_party/gcc/bin/x86_64-linux-musl-gcc
CXX = o/third_party/gcc/bin/x86_64-linux-musl-g++ CXX = o/third_party/gcc/bin/x86_64-linux-musl-g++
CXXFILT = o/third_party/gcc/bin/x86_64-linux-musl-c++filt CXXFILT = o/third_party/gcc/bin/x86_64-linux-musl-c++filt
LD = o/third_party/gcc/bin/x86_64-linux-musl-ld.bfd LD = o/third_party/gcc/bin/x86_64-linux-musl-ld.bfd
AR = o/third_party/gcc/bin/x86_64-linux-musl-ar AR = build/archive
NM = o/third_party/gcc/bin/x86_64-linux-musl-nm NM = o/third_party/gcc/bin/x86_64-linux-musl-nm
GCC = o/third_party/gcc/bin/x86_64-linux-musl-gcc GCC = o/third_party/gcc/bin/x86_64-linux-musl-gcc
STRIP = o/third_party/gcc/bin/x86_64-linux-musl-strip STRIP = o/third_party/gcc/bin/x86_64-linux-musl-strip
@ -295,7 +295,7 @@ PREPROCESS.lds = $(CC) $(PREPROCESS.lds.flags)
LINK = build/link $(LD) $(LINK.flags) LINK = build/link $(LD) $(LINK.flags)
ELF = o/libc/elf/elf.lds ELF = o/libc/elf/elf.lds
ELFLINK = ACTION=LINK.elf $(LINK) $(LINKARGS) $(OUTPUT_OPTION) ELFLINK = ACTION=LINK.elf $(LINK) $(LINKARGS) $(OUTPUT_OPTION)
ARCHIVE = build/archive $(AR) $(ARFLAGS) ARCHIVE = $(AR) $(ARFLAGS)
LINKARGS = $(patsubst %.lds,-T %.lds,$(call uniqr,$(LD.libs) $(filter-out %.pkg,$^))) LINKARGS = $(patsubst %.lds,-T %.lds,$(call uniqr,$(LD.libs) $(filter-out %.pkg,$^)))
LOLSAN = build/lolsan -b $(IMAGE_BASE_VIRTUAL) LOLSAN = build/lolsan -b $(IMAGE_BASE_VIRTUAL)

View File

@ -23,7 +23,7 @@ int main(int argc, char *argv[]) {
(tab = OpenSymbolTable(filename))) { (tab = OpenSymbolTable(filename))) {
for (unsigned i = 0; i < tab->count; ++i) { for (unsigned i = 0; i < tab->count; ++i) {
printf("%p %s\n", tab->addr_base + tab->symbols[i].addr_rva, printf("%p %s\n", tab->addr_base + tab->symbols[i].addr_rva,
getelfstring(tab->elf, tab->elfsize, tab->name_base, GetElfString(tab->elf, tab->elfsize, tab->name_base,
tab->symbols[i].name_rva)); tab->symbols[i].name_rva));
} }
} else { } else {

View File

@ -148,6 +148,36 @@ unsigned long hamming(unsigned long, unsigned long) pureconst;
Ple[7] = (uint8_t)(Vle >> 070); \ Ple[7] = (uint8_t)(Vle >> 070); \
} while (0) } while (0)
#define WRITE16BE(P, V) \
do { \
uint8_t *Ple = (uint8_t *)(P); \
uint16_t Vle = (V); \
Ple[1] = (uint8_t)(Vle >> 000); \
Ple[0] = (uint8_t)(Vle >> 010); \
} while (0)
#define WRITE32BE(P, V) \
do { \
uint8_t *Ple = (uint8_t *)(P); \
uint32_t Vle = (V); \
Ple[3] = (uint8_t)(Vle >> 000); \
Ple[2] = (uint8_t)(Vle >> 010); \
Ple[1] = (uint8_t)(Vle >> 020); \
Ple[0] = (uint8_t)(Vle >> 030); \
} while (0)
#define WRITE64BE(P, V) \
do { \
uint8_t *Ple = (uint8_t *)(P); \
uint64_t Vle = (V); \
Ple[7] = (uint8_t)(Vle >> 000); \
Ple[6] = (uint8_t)(Vle >> 010); \
Ple[5] = (uint8_t)(Vle >> 020); \
Ple[4] = (uint8_t)(Vle >> 030); \
Ple[3] = (uint8_t)(Vle >> 040); \
Ple[2] = (uint8_t)(Vle >> 050); \
Ple[1] = (uint8_t)(Vle >> 060); \
Ple[0] = (uint8_t)(Vle >> 070); \
} while (0)
/*───────────────────────────────────────────────────────────────────────────│─╗ /*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § bits » some assembly required cosmopolitan § bits » some assembly required
*/ */

View File

@ -79,12 +79,12 @@ bool isexecutable(const char *);
bool isregularfile(const char *); bool isregularfile(const char *);
bool32 isatty(int) nosideeffect; bool32 isatty(int) nosideeffect;
bool32 ischardev(int) nosideeffect; bool32 ischardev(int) nosideeffect;
char *commandv(const char *, char[hasatleast PATH_MAX]);
char *get_current_dir_name(void) nodiscard; char *get_current_dir_name(void) nodiscard;
char *getcwd(char *, size_t); char *getcwd(char *, size_t);
char *realpath(const char *, char *); char *realpath(const char *, char *);
char *replaceuser(const char *) nodiscard; char *replaceuser(const char *) nodiscard;
char *ttyname(int); char *ttyname(int);
char *commandv(const char *, char[hasatleast PATH_MAX]);
int access(const char *, int) nothrow; int access(const char *, int) nothrow;
int arch_prctl(); int arch_prctl();
int chdir(const char *); int chdir(const char *);
@ -120,6 +120,8 @@ int fstat(int, struct stat *);
int fstatat(int, const char *, struct stat *, uint32_t); int fstatat(int, const char *, struct stat *, uint32_t);
int fsync(int); int fsync(int);
int ftruncate(int, int64_t); int ftruncate(int, int64_t);
int getdomainname(char *, size_t);
int gethostname(char *, size_t);
int getppid(void); int getppid(void);
int getpriority(int, unsigned); int getpriority(int, unsigned);
int getrlimit(int, struct rlimit *); int getrlimit(int, struct rlimit *);
@ -161,18 +163,18 @@ int rmdir(const char *);
int sched_getaffinity(int, uint64_t, void *); int sched_getaffinity(int, uint64_t, void *);
int sched_setaffinity(int, uint64_t, const void *); int sched_setaffinity(int, uint64_t, const void *);
int sched_yield(void); int sched_yield(void);
int setegid(uint32_t);
int seteuid(uint32_t);
int setgid(uint32_t);
int setpgid(int, int); int setpgid(int, int);
int setpriority(int, unsigned, int); int setpriority(int, unsigned, int);
int setregid(uint32_t, uint32_t);
int setresgid(uint32_t, uint32_t, uint32_t);
int setresuid(uint32_t, uint32_t, uint32_t);
int setreuid(uint32_t, uint32_t);
int setrlimit(int, const struct rlimit *); int setrlimit(int, const struct rlimit *);
int setsid(void); int setsid(void);
int setuid(uint32_t); int setuid(uint32_t);
int setgid(uint32_t);
int seteuid(uint32_t);
int setegid(uint32_t);
int setreuid(uint32_t, uint32_t);
int setregid(uint32_t, uint32_t);
int setresuid(uint32_t, uint32_t, uint32_t);
int setresgid(uint32_t, uint32_t, uint32_t);
int sigaction(int, const struct sigaction *, struct sigaction *); int sigaction(int, const struct sigaction *, struct sigaction *);
int sigignore(int); int sigignore(int);
int sigprocmask(int, const struct sigset *, struct sigset *); int sigprocmask(int, const struct sigset *, struct sigset *);
@ -200,6 +202,7 @@ int64_t preadv(int, struct iovec *, int, int64_t);
int64_t pwrite(int, const void *, size_t, int64_t); int64_t pwrite(int, const void *, size_t, int64_t);
int64_t pwritev(int, const struct iovec *, int, int64_t); int64_t pwritev(int, const struct iovec *, int, int64_t);
int64_t syscall(); int64_t syscall();
void sync(void);
long telldir(DIR *); long telldir(DIR *);
int getpid(void); int getpid(void);
long times(struct tms *); long times(struct tms *);

View File

@ -16,10 +16,10 @@ LIBC_CALLS_ARTIFACTS += LIBC_CALLS_A
LIBC_CALLS = $(LIBC_CALLS_A_DEPS) $(LIBC_CALLS_A) LIBC_CALLS = $(LIBC_CALLS_A_DEPS) $(LIBC_CALLS_A)
LIBC_CALLS_A = o/$(MODE)/libc/calls/syscalls.a LIBC_CALLS_A = o/$(MODE)/libc/calls/syscalls.a
LIBC_CALLS_A_FILES := \ LIBC_CALLS_A_FILES := \
$(wildcard libc/calls/*) \
$(wildcard libc/calls/typedef/*) \ $(wildcard libc/calls/typedef/*) \
$(wildcard libc/calls/thunks/*) \ $(wildcard libc/calls/thunks/*) \
$(wildcard libc/calls/struct/*) \ $(wildcard libc/calls/struct/*)
$(wildcard libc/calls/*)
LIBC_CALLS_A_HDRS = $(filter %.h,$(LIBC_CALLS_A_FILES)) LIBC_CALLS_A_HDRS = $(filter %.h,$(LIBC_CALLS_A_FILES))
LIBC_CALLS_A_SRCS_S = $(filter %.S,$(LIBC_CALLS_A_FILES)) LIBC_CALLS_A_SRCS_S = $(filter %.S,$(LIBC_CALLS_A_FILES))
LIBC_CALLS_A_SRCS_C = $(filter %.c,$(LIBC_CALLS_A_FILES)) LIBC_CALLS_A_SRCS_C = $(filter %.c,$(LIBC_CALLS_A_FILES))

View File

@ -0,0 +1,53 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/utsname.h"
#include "libc/dce.h"
#include "libc/macros.h"
#include "libc/nt/enum/computernameformat.h"
#include "libc/nt/errors.h"
#include "libc/nt/runtime.h"
#include "libc/nt/systeminfo.h"
#include "libc/str/str.h"
#include "libc/sysv/errfuns.h"
int getdomainname(char *name, size_t len) {
uint32_t nSize;
char16_t name16[256];
struct utsname u;
if (len < 1) return einval();
if (!name) return efault();
if (!IsWindows()) {
if (uname(&u) == -1) return -1;
if (!memccpy(name, u.domainname[0] ? u.domainname : u.nodename, '\0',
len)) {
name[len - 1] = '\0';
}
return 0;
} else {
nSize = ARRAYLEN(name16);
if (!GetComputerNameEx(kNtComputerNameDnsFullyQualified, name16, &nSize)) {
return winerr();
}
tprecode16to8(name, MIN(MIN(ARRAYLEN(name16), nSize + 1), len), name16);
return 0;
}
}

View File

@ -0,0 +1,58 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/struct/utsname.h"
#include "libc/dce.h"
#include "libc/macros.h"
#include "libc/nt/enum/computernameformat.h"
#include "libc/nt/errors.h"
#include "libc/nt/runtime.h"
#include "libc/nt/systeminfo.h"
#include "libc/str/str.h"
#include "libc/sysv/errfuns.h"
/**
* Returns name of host system, e.g.
*
* pheidippides.domain.example
* ^^^^^^^^^^^^
*/
int gethostname(char *name, size_t len) {
uint32_t nSize;
char16_t name16[256];
struct utsname u;
if (len < 1) return einval();
if (!name) return efault();
if (!IsWindows()) {
if (uname(&u) == -1) return -1;
if (!memccpy(name, u.nodename, '\0', len)) {
name[len - 1] = '\0';
}
return 0;
} else {
nSize = ARRAYLEN(name16);
if (!GetComputerNameEx(kNtComputerNameDnsHostname, name16, &nSize)) {
return winerr();
}
tprecode16to8(name, MIN(MIN(ARRAYLEN(name16), nSize + 1), len), name16);
return 0;
}
}

View File

@ -49,7 +49,7 @@ __getntsyspath:
cmpb $'\\,-1(%rdi) cmpb $'\\,-1(%rdi)
jne 2f jne 2f
movb $'/,-1(%rdi) movb $'/,-1(%rdi)
2: loop 1b 2: .loop 1b
leave leave
ret ret
.endfn __getntsyspath,globl,hidden .endfn __getntsyspath,globl,hidden

View File

@ -161,6 +161,7 @@ i32 sigaction$sysv(i32, const void *, void *, i64) hidden;
i32 sigprocmask$sysv(i32, const sigset *, sigset *, u64) hidden; i32 sigprocmask$sysv(i32, const sigset *, sigset *, u64) hidden;
i32 sigsuspend$sysv(const sigset *, u64) hidden; i32 sigsuspend$sysv(const sigset *, u64) hidden;
i32 symlinkat$sysv(const char *, i32, const char *) hidden; i32 symlinkat$sysv(const char *, i32, const char *) hidden;
i32 sync$sysv(void) hidden;
i32 sync_file_range$sysv(i32, i64, i64, u32) hidden; i32 sync_file_range$sysv(i32, i64, i64, u32) hidden;
i32 sysinfo$sysv(struct sysinfo *) hidden; i32 sysinfo$sysv(struct sysinfo *) hidden;
i32 truncate$sysv(const char *, u64) hidden; i32 truncate$sysv(const char *, u64) hidden;
@ -239,6 +240,7 @@ int rename$nt(const char *, const char *) hidden;
int rmdir$nt(const char *) hidden; int rmdir$nt(const char *) hidden;
int sched_yield$nt(void) hidden; int sched_yield$nt(void) hidden;
int stat$nt(const char *, struct stat *) hidden; int stat$nt(const char *, struct stat *) hidden;
int sync$nt(void) hidden;
int symlink$nt(const char *, const char *) hidden; int symlink$nt(const char *, const char *) hidden;
int sysinfo$nt(struct sysinfo *) hidden; int sysinfo$nt(struct sysinfo *) hidden;
int truncate$nt(const char *, u64) hidden; int truncate$nt(const char *, u64) hidden;

View File

@ -21,6 +21,9 @@
#include "libc/calls/internal.h" #include "libc/calls/internal.h"
#include "libc/sysv/consts/at.h" #include "libc/sysv/consts/at.h"
/**
* Renames files relative to directories.
*/
int renameat(int olddirfd, const char *oldpath, int newdirfd, int renameat(int olddirfd, const char *oldpath, int newdirfd,
const char *newpath) { const char *newpath) {
unsigned mode; unsigned mode;

View File

@ -0,0 +1,54 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/nt/createfile.h"
#include "libc/nt/files.h"
#include "libc/nt/runtime.h"
#include "libc/sysv/consts/ok.h"
/**
* Flushes all open file handles and, if possible, all disk drives.
*/
int sync$nt(void) {
unsigned i;
int64_t volume;
uint32_t drives;
char16_t path[] = u"\\\\.\\C:";
for (i = 0; i < g_fds.n; ++i) {
if (g_fds.p[i].kind == kFdFile) {
FlushFileBuffers(g_fds.p[i].handle);
}
}
for (drives = GetLogicalDrives(), i = 0; i <= 'Z' - 'A'; ++i) {
if (!(drives & (1 << i))) continue;
path[4] = 'A' + i;
if (ntaccesscheck(path, R_OK | W_OK) != -1) {
if ((volume = CreateFile(
path, kNtFileReadAttributes,
kNtFileShareRead | kNtFileShareWrite | kNtFileShareDelete, 0,
kNtOpenExisting, 0, 0)) != -1) {
FlushFileBuffers(volume);
CloseHandle(volume);
}
}
}
return 0;
}

View File

@ -18,19 +18,16 @@
02110-1301 USA 02110-1301 USA
*/ */
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/runtime/runtime.h" #include "libc/calls/internal.h"
#include "libc/sysv/consts/map.h" #include "libc/dce.h"
#include "libc/sysv/consts/prot.h"
/** /**
* Allocates deterministic stack for process. * Flushes file system changes to disk to the greatest extent possible.
* @see _executive()
*/ */
void *_getstack(void) { void sync(void) {
char *p; if (!IsWindows()) {
p = mmap((char *)0x700000000000 /* IMAGE_BASE_VIRTUAL */ - STACKSIZE, sync$sysv();
STACKSIZE, PROT_READ | PROT_WRITE, } else {
MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); sync$nt();
if (p == MAP_FAILED) abort(); }
return p + STACKSIZE;
} }

View File

@ -22,6 +22,7 @@ size_t int64toarray_radix10(int64_t, char[hasatleast 21]);
size_t uint64toarray_radix10(uint64_t, char[hasatleast 21]); size_t uint64toarray_radix10(uint64_t, char[hasatleast 21]);
size_t uint64toarray_radix16(uint64_t, char[hasatleast 17]); size_t uint64toarray_radix16(uint64_t, char[hasatleast 17]);
size_t uint64toarray_fixed16(uint64_t, char[hasatleast 17], uint8_t); size_t uint64toarray_fixed16(uint64_t, char[hasatleast 17], uint8_t);
size_t uint64toarray_radix8(uint64_t, char[hasatleast 24]);
#ifndef __STRICT_ANSI__ #ifndef __STRICT_ANSI__
size_t int128toarray_radix10(int128_t, char *); size_t int128toarray_radix10(int128_t, char *);

View File

@ -17,21 +17,24 @@
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA 02110-1301 USA
*/ */
#include "libc/elf/def.h" #include "libc/alg/reverse.h"
#include "libc/elf/elf.h" #include "libc/conv/conv.h"
#include "libc/conv/itoa.h"
#include "libc/limits.h"
Elf64_Shdr *getelfsectionbyaddress(const Elf64_Ehdr *elf, size_t mapsize, /**
void *addr) { * Converts unsigned 64-bit integer to octal string.
Elf64_Half i; * @param a needs at least 24 bytes
Elf64_Shdr *shdr; * @return bytes written w/o nul
if (elf) { */
for (i = elf->e_shnum; i > 0; --i) { noinline size_t uint64toarray_radix8(uint64_t i, char a[hasatleast 24]) {
shdr = getelfsectionheaderaddress(elf, mapsize, i - 1); size_t j;
if ((intptr_t)addr >= shdr->sh_addr && j = 0;
(intptr_t)addr < shdr->sh_addr + shdr->sh_size) { do {
return shdr; a[j++] = i % 8 + '0';
} i /= 8;
} } while (i > 0);
} a[j] = '\0';
return NULL; reverse(a, j);
return j;
} }

View File

@ -20,10 +20,9 @@ COSMOPOLITAN_C_START_
struct MappedFile; struct MappedFile;
Elf64_Ehdr *mapelfread(const char *, struct MappedFile *); Elf64_Ehdr *mapelfread(const char *, struct MappedFile *);
char *getelfstringtable(const Elf64_Ehdr *, size_t); char *GetElfStringTable(const Elf64_Ehdr *, size_t);
Elf64_Sym *getelfsymboltable(const Elf64_Ehdr *, size_t, Elf64_Xword *); Elf64_Sym *GetElfSymbolTable(const Elf64_Ehdr *, size_t, Elf64_Xword *);
Elf64_Shdr *getelfsectionbyaddress(const Elf64_Ehdr *, size_t, void *); bool IsElf64Binary(const Elf64_Ehdr *, size_t);
bool iself64binary(const Elf64_Ehdr *, size_t);
forceinline void checkelfaddress(const Elf64_Ehdr *elf, size_t mapsize, forceinline void checkelfaddress(const Elf64_Ehdr *elf, size_t mapsize,
intptr_t addr, size_t addrsize) { intptr_t addr, size_t addrsize) {
@ -94,7 +93,7 @@ static inline void getelfvirtualaddressrange(const Elf64_Ehdr *elf,
if (out_end) *out_end = end; if (out_end) *out_end = end;
} }
static inline char *getelfstring(const Elf64_Ehdr *elf, size_t mapsize, static inline char *GetElfString(const Elf64_Ehdr *elf, size_t mapsize,
const char *strtab, Elf64_Word rva) { const char *strtab, Elf64_Word rva) {
intptr_t addr = (intptr_t)strtab + rva; intptr_t addr = (intptr_t)strtab + rva;
#if !(TRUSTWORTHY + ELF_TRUSTWORTHY + 0) #if !(TRUSTWORTHY + ELF_TRUSTWORTHY + 0)
@ -105,10 +104,10 @@ static inline char *getelfstring(const Elf64_Ehdr *elf, size_t mapsize,
return (char *)addr; return (char *)addr;
} }
static inline const char *getelfsectionname(const Elf64_Ehdr *elf, static inline const char *GetElfSectionName(const Elf64_Ehdr *elf,
size_t mapsize, Elf64_Shdr *shdr) { size_t mapsize, Elf64_Shdr *shdr) {
if (!elf || !shdr) return NULL; if (!elf || !shdr) return NULL;
return getelfstring(elf, mapsize, getelfsectionnamestringtable(elf, mapsize), return GetElfString(elf, mapsize, getelfsectionnamestringtable(elf, mapsize),
shdr->sh_name); shdr->sh_name);
} }

View File

@ -20,7 +20,7 @@
#include "libc/elf/def.h" #include "libc/elf/def.h"
#include "libc/elf/elf.h" #include "libc/elf/elf.h"
char *getelfstringtable(const Elf64_Ehdr *elf, size_t mapsize) { char *GetElfStringTable(const Elf64_Ehdr *elf, size_t mapsize) {
Elf64_Half i; Elf64_Half i;
Elf64_Shdr *shdr; Elf64_Shdr *shdr;
for (i = elf->e_shnum; i > 0; --i) { for (i = elf->e_shnum; i > 0; --i) {

View File

@ -20,7 +20,7 @@
#include "libc/elf/def.h" #include "libc/elf/def.h"
#include "libc/elf/elf.h" #include "libc/elf/elf.h"
Elf64_Sym *getelfsymboltable(const Elf64_Ehdr *elf, size_t mapsize, Elf64_Sym *GetElfSymbolTable(const Elf64_Ehdr *elf, size_t mapsize,
Elf64_Xword *out_count) { Elf64_Xword *out_count) {
Elf64_Half i; Elf64_Half i;
Elf64_Shdr *shdr; Elf64_Shdr *shdr;

View File

@ -19,7 +19,7 @@
*/ */
#include "libc/elf/elf.h" #include "libc/elf/elf.h"
bool iself64binary(const Elf64_Ehdr *elf, size_t mapsize) { bool IsElf64Binary(const Elf64_Ehdr *elf, size_t mapsize) {
if (mapsize < sizeof(Elf64_Ehdr)) return false; if (mapsize < sizeof(Elf64_Ehdr)) return false;
if (memcmp(elf->e_ident, ELFMAG, 4)) return false; if (memcmp(elf->e_ident, ELFMAG, 4)) return false;
return (elf->e_ident[EI_CLASS] == ELFCLASSNONE || return (elf->e_ident[EI_CLASS] == ELFCLASSNONE ||

View File

@ -10,6 +10,7 @@ typedef struct Elf64_Sym {
uint8_t st_info; uint8_t st_info;
/* STV_{DEFAULT,INTERNAL,HIDDEN,PROTECTED} */ /* STV_{DEFAULT,INTERNAL,HIDDEN,PROTECTED} */
uint8_t st_other; uint8_t st_other;
/* SHN_UNDEF, <section index>, SHN_ABS, SHN_COMMON, etc. */
Elf64_Section st_shndx; Elf64_Section st_shndx;
Elf64_Addr st_value; Elf64_Addr st_value;
Elf64_Xword st_size; Elf64_Xword st_size;

View File

@ -63,7 +63,7 @@ int strerror_r(int err, char *buf, size_t size) {
if (FormatMessage( if (FormatMessage(
kNtFormatMessageFromSystem | kNtFormatMessageIgnoreInserts, NULL, kNtFormatMessageFromSystem | kNtFormatMessageIgnoreInserts, NULL,
err, 0, buf16, ARRAYLEN(buf16) - 1, 0) > 0) { err, 0, buf16, ARRAYLEN(buf16) - 1, 0) > 0) {
chomp(buf16); chomp16(buf16);
} else { } else {
buf16[0] = u'\0'; buf16[0] = u'\0';
} }

View File

@ -152,6 +152,7 @@ relegated static void ShowMemoryMappings(int outfd) {
relegated static void ShowCrashReport(int err, int fd, int sig, relegated static void ShowCrashReport(int err, int fd, int sig,
ucontext_t *ctx) { ucontext_t *ctx) {
int i;
struct utsname names; struct utsname names;
(dprintf)(fd, VEIL("r", "\r\n%serror%s: Uncaught SIG%s\r\n %s\r\n %s\r\n"), (dprintf)(fd, VEIL("r", "\r\n%serror%s: Uncaught SIG%s\r\n %s\r\n %s\r\n"),
RED2, RESET, TinyStrSignal(sig), getauxval(AT_EXECFN), RED2, RESET, TinyStrSignal(sig), getauxval(AT_EXECFN),
@ -167,6 +168,11 @@ relegated static void ShowCrashReport(int err, int fd, int sig,
} }
write(fd, "\r\n", 2); write(fd, "\r\n", 2);
ShowMemoryMappings(fd); ShowMemoryMappings(fd);
write(fd, "\r\n", 2);
for (i = 0; i < g_argc; ++i) {
write(fd, g_argv[i], strlen(g_argv[i]));
write(fd, "\r\n", 2);
}
} }
relegated static void RestoreDefaultCrashSignalHandlers(void) { relegated static void RestoreDefaultCrashSignalHandlers(void) {

View File

@ -186,10 +186,10 @@
.endif .endif
.endm .endm
/ Overrides LOOP instruction. / LOOP Instruction Replacement.
/ With its mop-Fusion Mexican equivalent. / With its mop-Fusion Mexican equivalent.
/ Thus avoiding 3x legacy pipeline slowdown. / Thus avoiding 3x legacy pipeline slowdown.
.macro loop label:req .macro .loop label:req
.byte 0x83,0xe9,0x01 # sub $1,%ecx .byte 0x83,0xe9,0x01 # sub $1,%ecx
jnz \label jnz \label
.endm .endm

View File

@ -59,7 +59,7 @@ crc32init:
pand %xmm0,%xmm3 pand %xmm0,%xmm3
pxor %xmm4,%xmm3 pxor %xmm4,%xmm3
movdqa %xmm3,%xmm4 movdqa %xmm3,%xmm4
loop 2b .loop 2b
movdqu %xmm3,(%rdi) movdqu %xmm3,(%rdi)
add $16,%rdi add $16,%rdi
paddd %xmm2,%xmm1 paddd %xmm2,%xmm1

View File

@ -35,7 +35,7 @@ imapxlatab:
.align 8 .align 8
1: stosq 1: stosq
add %rdx,%rax add %rdx,%rax
loop 1b .loop 1b
.leafepilogue .leafepilogue
.endfn imapxlatab,globl,hidden .endfn imapxlatab,globl,hidden
.source __FILE__ .source __FILE__

View File

@ -35,13 +35,13 @@ kBase36:.zero 256
pushpop 10,%rcx pushpop 10,%rcx
0: inc %eax 0: inc %eax
stosb stosb
loop 0b .loop 0b
add $'A-1-'9,%rdi add $'A-1-'9,%rdi
pushpop 'Z+1-'A,%rcx pushpop 'Z+1-'A,%rcx
0: inc %eax 0: inc %eax
mov %al,0x20(%rdi) mov %al,0x20(%rdi)
stosb stosb
loop 0b .loop 0b
add $255-'Z,%rdi add $255-'Z,%rdi
.init.end 300,_init_kBase36 .init.end 300,_init_kBase36
.source __FILE__ .source __FILE__

View File

@ -51,7 +51,7 @@ kToLower16:
mov $256,%ecx mov $256,%ecx
0: lodsb 0: lodsb
stosw stosw
loop 0b .loop 0b
pop %rsi pop %rsi
.init.end 300,_init_kToLower .init.end 300,_init_kToLower

View File

@ -30,6 +30,6 @@ kToUpper:
call imapxlatab call imapxlatab
pushpop 'z-'a,%rcx pushpop 'z-'a,%rcx
0: subb $0x20,(%r8,%rcx) 0: subb $0x20,(%r8,%rcx)
loop 0b .loop 0b
.init.end 300,_init_kToUpper .init.end 300,_init_kToUpper
.source __FILE__ .source __FILE__

View File

@ -36,7 +36,7 @@ memjmpinit:
lodsb lodsb
add %rdx,%rax add %rdx,%rax
stosq stosq
loop 0b .loop 0b
xor %eax,%eax xor %eax,%eax
testb X86_HAVE(ERMS)+kCpuids(%rip) testb X86_HAVE(ERMS)+kCpuids(%rip)
setnz %al setnz %al

View File

@ -34,7 +34,7 @@ rldecode:
lodsb lodsb
jrcxz 2f jrcxz 2f
1: stosb 1: stosb
loop 1b .loop 1b
jmp 0b jmp 0b
2: .leafepilogue 2: .leafepilogue
.endfn rldecode,globl .endfn rldecode,globl

View File

@ -1,2 +1,12 @@
.include "o/libc/nt/codegen.inc" .include "o/libc/nt/codegen.inc"
.imp KernelBase,__imp_GetComputerNameExW,GetComputerNameExW,449 .imp KernelBase,__imp_GetComputerNameExW,GetComputerNameExW,449
.text.windows
GetComputerNameEx:
push %rbp
mov %rsp,%rbp
.profilable
mov __imp_GetComputerNameExW(%rip),%rax
jmp __sysv2nt
.endfn GetComputerNameEx,globl
.previous

View File

@ -0,0 +1,16 @@
#ifndef COSMOPOLITAN_LIBC_NT_ENUM_COMPUTERNAMEFORMAT_H_
#define COSMOPOLITAN_LIBC_NT_ENUM_COMPUTERNAMEFORMAT_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
#define kNtComputerNameNetBios 0
#define kNtComputerNameDnsHostname 1
#define kNtComputerNameDnsDomain 2
#define kNtComputerNameDnsFullyQualified 3
#define kNtComputerNamePhysicalNetBios 4
#define kNtComputerNamePhysicalDnsHostname 5
#define kNtComputerNamePhysicalDnsDomain 6
#define kNtComputerNamePhysicalDnsFullyQualified 7
#define kNtComputerName_MAX 8
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_NT_ENUM_COMPUTERNAMEFORMAT_H_ */

View File

@ -1979,7 +1979,7 @@ imp 'GetCompressedFileSizeTransactedA' GetCompressedFileSizeTransactedA kern
imp 'GetCompressedFileSizeTransacted' GetCompressedFileSizeTransactedW kernel32 479 imp 'GetCompressedFileSizeTransacted' GetCompressedFileSizeTransactedW kernel32 479
imp 'GetComputerNameA' GetComputerNameA kernel32 481 imp 'GetComputerNameA' GetComputerNameA kernel32 481
imp 'GetComputerNameExA' GetComputerNameExA KernelBase 448 imp 'GetComputerNameExA' GetComputerNameExA KernelBase 448
imp 'GetComputerNameEx' GetComputerNameExW KernelBase 449 imp 'GetComputerNameEx' GetComputerNameExW KernelBase 449 3
imp 'GetComputerName' GetComputerNameW kernel32 484 imp 'GetComputerName' GetComputerNameW kernel32 484
imp 'GetConsoleAliasA' GetConsoleAliasA KernelBase 450 imp 'GetConsoleAliasA' GetConsoleAliasA KernelBase 450
imp 'GetConsoleAliasExesA' GetConsoleAliasExesA KernelBase 451 imp 'GetConsoleAliasExesA' GetConsoleAliasExesA KernelBase 451

View File

@ -46,12 +46,14 @@ int64_t CreateFileMappingNuma(
const struct NtSecurityAttributes *opt_lpFileMappingAttributes, const struct NtSecurityAttributes *opt_lpFileMappingAttributes,
uint32_t flProtect, uint32_t dwMaximumSizeHigh, uint32_t dwMaximumSizeLow, uint32_t flProtect, uint32_t dwMaximumSizeHigh, uint32_t dwMaximumSizeLow,
const char16_t *opt_lpName, uint32_t nndDesiredNumaNode); const char16_t *opt_lpName, uint32_t nndDesiredNumaNode);
void *MapViewOfFileExNuma( void *MapViewOfFileExNuma(
int64_t hFileMappingObject, /* @see CreateFileMapping() */ int64_t hFileMappingObject, /* @see CreateFileMapping() */
uint32_t dwDesiredAccess, uint32_t dwFileOffsetHigh, /* high order bits */ uint32_t dwDesiredAccess, uint32_t dwFileOffsetHigh, /* high order bits */
uint32_t dwFileOffsetLow, /* low order bits */ uint32_t dwFileOffsetLow, /* low order bits */
size_t dwNumberOfBytesToMap, void *opt_lpDesiredBaseAddress, size_t dwNumberOfBytesToMap, void *opt_lpDesiredBaseAddress,
uint32_t nndDesiredNumaNode); uint32_t nndDesiredNumaNode);
bool32 UnmapViewOfFile(const void *lpBaseAddress); bool32 UnmapViewOfFile(const void *lpBaseAddress);
bool32 FlushViewOfFile(const void *lpBaseAddress, bool32 FlushViewOfFile(const void *lpBaseAddress,
size_t dwNumberOfBytesToFlush); size_t dwNumberOfBytesToFlush);

View File

@ -152,6 +152,8 @@ $(LIBC_NT_NTDLL_A): \
libc/nt/ntdll/ \ libc/nt/ntdll/ \
$(LIBC_NT_NTDLL_A).pkg \ $(LIBC_NT_NTDLL_A).pkg \
$(LIBC_NT_NTDLL_A_OBJS) $(LIBC_NT_NTDLL_A_OBJS)
@$(file >$@.cmd) $(file >>$@.cmd,$(ARCHIVE) $@ $^ >$(LIBC_NT_NTDLL_A).cmd)
@$(ARCHIVE) $@ $^
$(LIBC_NT_NTDLL_A).pkg: \ $(LIBC_NT_NTDLL_A).pkg: \
$(LIBC_NT_NTDLL_A_OBJS) \ $(LIBC_NT_NTDLL_A_OBJS) \

View File

@ -13,6 +13,9 @@ uint32_t GetSystemDirectoryA(char *lpBuffer, uint32_t uSize);
uint32_t GetWindowsDirectory(char16_t *lpBuffer, uint32_t uSize); uint32_t GetWindowsDirectory(char16_t *lpBuffer, uint32_t uSize);
uint32_t GetTempPath(uint32_t uSize, char16_t *lpBuffer); uint32_t GetTempPath(uint32_t uSize, char16_t *lpBuffer);
bool32 GetComputerNameEx(/* enum/computernameformat.h */ int NameType,
char16_t *opt_lpBuffer, uint32_t *nSize);
#if ShouldUseMsabiAttribute() #if ShouldUseMsabiAttribute()
#include "libc/nt/thunk/systeminfo.inc" #include "libc/nt/thunk/systeminfo.inc"
#endif /* ShouldUseMsabiAttribute() */ #endif /* ShouldUseMsabiAttribute() */

View File

@ -38,8 +38,8 @@ static textwindows struct DirectMap DirectMapNt(void *addr, size_t size,
protect = prot2nt(prot, flags); protect = prot2nt(prot, flags);
access = fprot2nt(prot, flags); access = fprot2nt(prot, flags);
if ((res.maphandle = if ((res.maphandle =
CreateFileMappingNuma(handle, &kNtIsInheritable, protect, size >> 32, CreateFileMappingNuma(handle, NULL, protect, size >> 32, size, NULL,
size, NULL, kNtNumaNoPreferredNode))) { kNtNumaNoPreferredNode))) {
if (!(res.addr = MapViewOfFileExNuma(res.maphandle, access, off >> 32, off, if (!(res.addr = MapViewOfFileExNuma(res.maphandle, access, off >> 32, off,
size, addr, kNtNumaNoPreferredNode))) { size, addr, kNtNumaNoPreferredNode))) {
CloseHandle(res.maphandle); CloseHandle(res.maphandle);

View File

@ -42,16 +42,13 @@ _executive:
mov %rdx,%r14 mov %rdx,%r14
mov %rcx,%r15 mov %rcx,%r15
call _spawn call _spawn
call _getstack mov %r12d,%edi
mov %rax,%rdi mov %r13,%rsi
mov %r14,%rdx
mov %r15,%rcx
.weak main .weak main
mov $main,%esi call main
mov %r12,%rdx xchg %eax,%edi
mov %r13,%rcx
mov %r14,%r8
mov %r15,%r9
call _setstack
mov %eax,%edi
call exit call exit
.endfn _executive,weak,hidden .endfn _executive,weak,hidden
ud2 ud2

View File

@ -25,6 +25,7 @@ void *__cxa_finalize(void *) hidden;
void _executive(int, char **, char **, long (*)[2]) hidden noreturn; void _executive(int, char **, char **, long (*)[2]) hidden noreturn;
void __stack_chk_fail(void) noreturn relegated; void __stack_chk_fail(void) noreturn relegated;
void __stack_chk_fail_local(void) noreturn relegated hidden; void __stack_chk_fail_local(void) noreturn relegated hidden;
long _setstack(void *, void *, ...) hidden;
int GetDosArgv(const char16_t *, char *, size_t, char **, size_t) hidden; int GetDosArgv(const char16_t *, char *, size_t, char **, size_t) hidden;
forceinline void AssertNeverCalledWhileTerminating(void) { forceinline void AssertNeverCalledWhileTerminating(void) {

View File

@ -22,7 +22,7 @@
#include "libc/runtime/ezmap.h" #include "libc/runtime/ezmap.h"
Elf64_Ehdr *mapelfread(const char *filename, struct MappedFile *mf) { Elf64_Ehdr *mapelfread(const char *filename, struct MappedFile *mf) {
if (mapfileread(filename, mf) != -1 && iself64binary(mf->addr, mf->size)) { if (mapfileread(filename, mf) != -1 && IsElf64Binary(mf->addr, mf->size)) {
return mf->addr; return mf->addr;
} else { } else {
unmapfile(mf); unmapfile(mf);

View File

@ -27,7 +27,9 @@
/** /**
* Synchronize memory mapping changes to disk. * Synchronize memory mapping changes to disk.
* *
* @param flags needs MS_SYNC or MS_ASYNC and can have MS_INVALIDATE * Without this, there's no guarantee memory is written back to disk.
*
* @param flags needs MS_ASYNC or MS_SYNC and can have MS_INVALIDATE
* @return 0 on success or -1 w/ errno * @return 0 on success or -1 w/ errno
*/ */
int msync(void *addr, size_t size, int flags) { int msync(void *addr, size_t size, int flags) {

View File

@ -39,8 +39,8 @@ struct SymbolTable *OpenSymbolTable(const char *filename) {
t = MAP_FAILED; t = MAP_FAILED;
if (filename && (t = mapanon(BIGPAGESIZE)) != MAP_FAILED && if (filename && (t = mapanon(BIGPAGESIZE)) != MAP_FAILED &&
mapelfread(filename, &t->mf) && mapelfread(filename, &t->mf) &&
(t->name_base = getelfstringtable(t->elf, t->elfsize)) != NULL && (t->name_base = GetElfStringTable(t->elf, t->elfsize)) != NULL &&
(symtab = getelfsymboltable(t->elf, t->elfsize, &t->count)) && (symtab = GetElfSymbolTable(t->elf, t->elfsize, &t->count)) &&
sizeof(struct SymbolTable) + sizeof(struct Symbol) * t->count < sizeof(struct SymbolTable) + sizeof(struct Symbol) * t->count <
(t->scratch = BIGPAGESIZE)) { (t->scratch = BIGPAGESIZE)) {
getelfvirtualaddressrange(t->elf, t->elfsize, &t->addr_base, &t->addr_end); getelfvirtualaddressrange(t->elf, t->elfsize, &t->addr_base, &t->addr_end);

View File

@ -43,7 +43,6 @@ void longjmp(jmp_buf, int) libcesque noreturn paramsnonnull();
void exit(int) noreturn; void exit(int) noreturn;
void _exit(int) libcesque noreturn; void _exit(int) libcesque noreturn;
void _Exit(int) libcesque noreturn; void _Exit(int) libcesque noreturn;
long _setstack(void *, void *, ...);
void abort(void) noreturn noinstrument; void abort(void) noreturn noinstrument;
void panic(void) noreturn noinstrument privileged; void panic(void) noreturn noinstrument privileged;
void triplf(void) noreturn noinstrument privileged; void triplf(void) noreturn noinstrument privileged;

View File

@ -24,7 +24,7 @@
/ @param rdi is new rsp, passed as malloc(size) + size / @param rdi is new rsp, passed as malloc(size) + size
/ @param rsi is function to call in new stack space / @param rsi is function to call in new stack space
/ @param rdx,rcx,r8,r9 get passed as args to rsi / @param rdx,rcx,r8,r9 get passed as args to rsi
/ @return happens on original stack / @return rax and happens on original stack
_setstack: _setstack:
push %rbp push %rbp
mov %rsp,%rbp mov %rsp,%rbp
@ -43,4 +43,4 @@ _setstack:
pop %rbx pop %rbx
pop %rbp pop %rbp
ret ret
.endfn _setstack,globl .endfn _setstack,globl,hidden

View File

@ -25,7 +25,9 @@
#include "libc/nt/enum/consolemodeflags.h" #include "libc/nt/enum/consolemodeflags.h"
#include "libc/nt/enum/filetype.h" #include "libc/nt/enum/filetype.h"
#include "libc/nt/enum/loadlibrarysearch.h" #include "libc/nt/enum/loadlibrarysearch.h"
#include "libc/nt/enum/pageflags.h"
#include "libc/nt/files.h" #include "libc/nt/files.h"
#include "libc/nt/memory.h"
#include "libc/nt/pedef.h" #include "libc/nt/pedef.h"
#include "libc/nt/process.h" #include "libc/nt/process.h"
#include "libc/nt/runtime.h" #include "libc/nt/runtime.h"
@ -117,10 +119,10 @@ static textwindows void NormalizeCmdExe(void) {
* 3. Environment variables are passed to us as a sorted UTF-16 double * 3. Environment variables are passed to us as a sorted UTF-16 double
* NUL terminated list. We translate this to char ** using UTF-8. * NUL terminated list. We translate this to char ** using UTF-8.
* *
* 4. NT likes to choose a stack address that's beneath the program * 4. Allocates new stack at a high address. NT likes to choose a
* image. We want to be able to assume that stack addresses are * stack address that's beneath the program image. We want to be
* located at higher addresses than heap and program memory. So the * able to assume that stack addresses are located at higher
* _executive() function will switch stacks appropriately. * addresses than heap and program memory.
* *
* 5. Windows users are afraid of "drive-by downloads" where someone * 5. Windows users are afraid of "drive-by downloads" where someone
* might accidentally an evil DLL to their Downloads folder which * might accidentally an evil DLL to their Downloads folder which
@ -131,21 +133,27 @@ static textwindows void NormalizeCmdExe(void) {
*/ */
textwindows int WinMain(void *hInstance, void *hPrevInstance, textwindows int WinMain(void *hInstance, void *hPrevInstance,
const char *lpCmdLine, int nCmdShow) { const char *lpCmdLine, int nCmdShow) {
char *stack;
int i, count; int i, count;
const char16_t *cmd16, *env16; const char16_t *cmd16, *env16;
char *argarray[512], *envarray[512]; char *argv[512], *envp[512];
char argblock[ARG_MAX], envblock[ENV_MAX]; char argblock[ARG_MAX], envblock[ENV_MAX];
long auxarray[][2] = {{pushpop(0L), pushpop(0L)}}; long auxv[][2] = {{pushpop(0L), pushpop(0L)}};
MitigateDriveByDownloads(); MitigateDriveByDownloads();
NormalizeCmdExe(); NormalizeCmdExe();
*(/*unconst*/ int *)&hostos = WINDOWS; *(/*unconst*/ int *)&hostos = WINDOWS;
cmd16 = GetCommandLine(); cmd16 = GetCommandLine();
env16 = GetEnvironmentStrings(); env16 = GetEnvironmentStrings();
count = GetDosArgv(cmd16, argblock, ARG_MAX, argarray, 512); count = GetDosArgv(cmd16, argblock, ARG_MAX, argv, 512);
for (i = 0; argarray[0][i]; ++i) { for (i = 0; argv[0][i]; ++i) {
if (argarray[0][i] == '\\') argarray[0][i] = '/'; if (argv[0][i] == '\\') argv[0][i] = '/';
} }
GetDosEnviron(env16, envblock, ENV_MAX, envarray, 512); GetDosEnviron(env16, envblock, ENV_MAX, envp, 512);
FreeEnvironmentStrings(env16); FreeEnvironmentStrings(env16);
_executive(count, argarray, envarray, auxarray); stack = MapViewOfFileExNuma(
CreateFileMappingNuma(-1, NULL, pushpop(kNtPageReadwrite), 0, STACKSIZE,
NULL, kNtNumaNoPreferredNode),
kNtFileMapRead | kNtFileMapWrite, 0, 0, STACKSIZE,
(char *)0x777000000000 - STACKSIZE, kNtNumaNoPreferredNode);
return _setstack(stack + STACKSIZE, _executive, count, argv, envp, auxv);
} }

View File

@ -256,97 +256,6 @@ bool luhn(const char *);
char *strsignal(int) returnsnonnull libcesque; char *strsignal(int) returnsnonnull libcesque;
/*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § strings » hooks
*/
#if defined(__GNUC__) && !defined(__STRICT_ANSI__)
extern int (*const hook$strcmp16)(const char16_t *, const char16_t *);
extern int (*const hook$strncmp16)(const char16_t *, const char16_t *, size_t);
extern int (*const hook$wcscmp)(const wchar_t *, const wchar_t *);
extern int (*const hook$wcsncmp)(const wchar_t *, const wchar_t *, size_t);
#define __STR_HOOK(SYMBOL) hook$##SYMBOL
#else
#define __STR_HOOK(SYMBOL) SYMBOL
#endif /* GNUC && !ANSI */
/* TODO(jart): Use @gotpcrel. */
#undef __STR_HOOK
#define __STR_HOOK(SYMBOL) SYMBOL
/*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § strings » generic typing
*/
#if __STDC_VERSION__ + 0 >= 201112
#define strnlen(s, n) \
_Generic(*(s), wchar_t \
: wcsnlen, char16_t \
: strnlen16, default \
: strnlen)(s, n)
#define strnlen_s(s, n) \
_Generic(*(s), wchar_t \
: wcsnlen_s, char16_t \
: strnlen16_s, default \
: strnlen_s)(s, n)
#define strpbrk(s, c) \
_Generic(*(s), wchar_t \
: wcspbrk, char16_t \
: strpbrk16, default \
: strpbrk)(s, c)
#define strspn(s, c) \
_Generic(*(s), wchar_t : wcsspn, char16_t : strspn16, default : strspn)(s, c)
#define strcspn(s, c) \
_Generic(*(s), wchar_t \
: wcscspn, char16_t \
: strcspn16, default \
: strcspn)(s, c)
/* clang-format off */
#define strcmp(s1, s2) \
_Generic((s1)[0], \
wchar_t: __STR_HOOK(wcscmp), \
char16_t: _Generic(*(s2), \
char: strcmp16to8, \
default: __STR_HOOK(strcmp16)), \
default: _Generic(*(s2), \
char16_t: strcmp8to16, \
default: strcmp))(s1, s2)
/* clang-format on */
#define strncmp(s1, s2, n) \
_Generic(*(s1), wchar_t \
: __STR_HOOK(wcsncmp), char16_t \
: _Generic(*(s2), char \
: strncmp16to8, default \
: __STR_HOOK(strncmp16)), \
default \
: _Generic(*(s2), char16_t \
: strncmp8to16, default \
: strncmp))(s1, s2, n)
#define strcasecmp(s1, s2) \
_Generic(*(s1), wchar_t \
: wcscasecmp, char16_t \
: strcasecmp16, default \
: strcasecmp)(s1, s2)
#define strncasecmp(s1, s2, n) \
_Generic(*(s1), wchar_t \
: wcsncasecmp, char16_t \
: strncasecmp16, default \
: strncasecmp)(s1, s2, n)
#define chomp(s) \
_Generic(*(s), wchar_t : wchomp, char16_t : chomp16, default : chomp)(s)
#endif /* C11 */
/*───────────────────────────────────────────────────────────────────────────│─╗ /*───────────────────────────────────────────────────────────────────────────│─╗
cosmopolitan § strings » optimizations cosmopolitan § strings » optimizations
*/ */

View File

@ -28,7 +28,7 @@
* @see strspn(), strtok_r() * @see strspn(), strtok_r()
* @asyncsignalsafe * @asyncsignalsafe
*/ */
size_t(strcspn)(const char *s, const char *reject) { size_t strcspn(const char *s, const char *reject) {
size_t i; size_t i;
for (i = 0; s[i]; ++i) { for (i = 0; s[i]; ++i) {
if (HasCharacter(s[i], reject)) { if (HasCharacter(s[i], reject)) {

View File

@ -20,9 +20,20 @@
#include "libc/nexgen32e/hascharacter.h" #include "libc/nexgen32e/hascharacter.h"
#include "libc/str/str.h" #include "libc/str/str.h"
#undef strcspn /**
#define char char16_t * Returns prefix length, consisting of chars not in reject.
#define HasCharacter HasCharacter16 * a.k.a. Return index of first byte that's in charset.
#define strcspn strcspn16 *
* @param reject is nul-terminated character set
#include "libc/str/strcspn.c" * @see strspn(), strtok_r()
* @asyncsignalsafe
*/
size_t strcspn16(const char16_t *s, const char16_t *reject) {
size_t i;
for (i = 0; s[i]; ++i) {
if (HasCharacter16(s[i], reject)) {
break;
}
}
return i;
}

View File

@ -20,9 +20,20 @@
#include "libc/nexgen32e/hascharacter.h" #include "libc/nexgen32e/hascharacter.h"
#include "libc/str/str.h" #include "libc/str/str.h"
#undef strcspn /**
#define char wchar_t * Returns prefix length, consisting of chars not in reject.
#define HasCharacter HasCharacterWide * a.k.a. Return index of first byte that's in charset.
#define strcspn wcscspn *
* @param reject is nul-terminated character set
#include "libc/str/strcspn.c" * @see strspn(), strtok_r()
* @asyncsignalsafe
*/
size_t wcscspn(const wchar_t *s, const wchar_t *reject) {
size_t i;
for (i = 0; s[i]; ++i) {
if (HasCharacterWide(s[i], reject)) {
break;
}
}
return i;
}

View File

@ -1,2 +0,0 @@
.include "o/libc/sysv/macros.inc"
.scall gethostname 0xffff0057ffffffff globl

View File

@ -0,0 +1,2 @@
.include "o/libc/sysv/macros.inc"
.scall sync$sysv 0x00240024202400a2 globl hidden

View File

@ -1,2 +0,0 @@
.include "o/libc/sysv/macros.inc"
.scall sync 0x00240024202400a2 globl

View File

@ -178,7 +178,7 @@ scall mlockall 0x010f014421440097 globl
scall munlockall 0x0110014521450098 globl scall munlockall 0x0110014521450098 globl
scall 'setrlimit$sysv' 0x00c300c320c300a0 globl hidden scall 'setrlimit$sysv' 0x00c300c320c300a0 globl hidden
scall chroot 0x003d003d203d00a1 globl scall chroot 0x003d003d203d00a1 globl
scall sync 0x00240024202400a2 globl scall 'sync$sysv' 0x00240024202400a2 globl hidden
scall acct 0x00330033203300a3 globl scall acct 0x00330033203300a3 globl
scall settimeofday 0x0044007a207a00a4 globl scall settimeofday 0x0044007a207a00a4 globl
scall mount 0x0015001520a700a5 globl scall mount 0x0015001520a700a5 globl
@ -649,10 +649,10 @@ scall fhlinkat 0xffff0236ffffffff globl
scall fhreadlink 0xffff0237ffffffff globl scall fhreadlink 0xffff0237ffffffff globl
scall getaudit 0xffff01c1ffffffff globl scall getaudit 0xffff01c1ffffffff globl
scall getcontext 0xffff01a5ffffffff globl scall getcontext 0xffff01a5ffffffff globl
scall getdomainname 0xffff00a2ffffffff globl #scall getdomainname 0xffff00a2ffffffff globl
scall getfhat 0xffff0234ffffffff globl scall getfhat 0xffff0234ffffffff globl
scall gethostid 0xffff008effffffff globl scall gethostid 0xffff008effffffff globl
scall gethostname 0xffff0057ffffffff globl #scall gethostname 0xffff0057ffffffff globl
scall getkerninfo 0xffff003fffffffff globl scall getkerninfo 0xffff003fffffffff globl
scall getloginclass 0xffff020bffffffff globl scall getloginclass 0xffff020bffffffff globl
scall 'getpagesize$freebsd' 0xffff0040ffffffff globl hidden scall 'getpagesize$freebsd' 0xffff0040ffffffff globl hidden

255
tool/build/ar.c 100644
View File

@ -0,0 +1,255 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/alg/arraylist2.h"
#include "libc/bits/bits.h"
#include "libc/calls/calls.h"
#include "libc/calls/struct/iovec.h"
#include "libc/calls/struct/stat.h"
#include "libc/conv/conv.h"
#include "libc/conv/itoa.h"
#include "libc/elf/def.h"
#include "libc/elf/elf.h"
#include "libc/errno.h"
#include "libc/log/check.h"
#include "libc/macros.h"
#include "libc/sock/sock.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/madv.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/prot.h"
#include "libc/x/x.h"
/**
* @fileoverview System Five Static Archive Builder.
*
* GNU ar has a bug which causes it to take hundreds of milliseconds to
* build archives like ntdll.a and several minutes for cosmopolitan.a.
* This goes quadratically faster taking 1ms to do ntdll w/ hot cache.
*
* Compared to LLVM ar this tool goes 10x faster because it uses madvise
* and copy_file_range which give us the optimal page cached file system
* beahvior that a build environment needs.
*
* This tool also adds a feature: it ignores directory parameters. This
* is important because good Makefiles on Linux will generally have the
* directory be a .a prerequisite so archives rebuild on file deletion.
*/
struct String {
size_t i, n;
char *p;
};
struct Ints {
size_t i, n;
int *p;
};
struct Header {
char name[16];
char date[12];
char uid[6];
char gid[6];
char mode[8];
char size[10];
char fmag[2];
};
static void MakeHeader(struct Header *h, const char *name, int ref, int mode,
int size) {
size_t n;
char buf[21];
memset(h, ' ', sizeof(*h));
n = strlen(name);
memcpy(h->name, name, n);
if (ref != -1) {
memcpy(h->name + n, buf, uint64toarray_radix10(ref, buf));
}
if (strcmp(name, "//") != 0) {
h->date[0] = '0';
h->uid[0] = '0';
h->gid[0] = '0';
memcpy(h->mode, buf, uint64toarray_radix8(mode & 0777, buf));
}
h->fmag[0] = '`';
h->fmag[1] = '\n';
memcpy(h->size, buf, uint64toarray_radix10(size, buf));
}
int main(int argc, char *argv[]) {
void *elf;
char *strs;
ssize_t rc;
struct stat *st;
uint32_t outpos;
Elf64_Sym *syms;
uint64_t outsize;
char **objectargs;
uint8_t *tablebuf;
struct iovec iov[7];
const char *symname;
Elf64_Xword symcount;
struct Ints symnames;
struct String symbols;
struct String filenames;
const char *options, *outpath;
struct Header *header1, *header2;
size_t wrote, remain, objectargcount;
int *offsets, *modes, *sizes, *names;
int i, j, fd, err, name, outfd, tablebufsize;
st = xmalloc(sizeof(struct stat));
symbols.i = 0;
symbols.n = 4096;
symbols.p = xmalloc(symbols.n);
filenames.i = 0;
filenames.n = 1024;
filenames.p = xmalloc(filenames.n);
symnames.i = 0;
symnames.n = 1024;
symnames.p = xmalloc(symnames.n * sizeof(int));
CHECK_GT(argc, 3);
options = argv[1];
outpath = argv[2];
objectargs = argv + 3;
objectargcount = argc - 3;
CHECK_EQ(0, strcmp(options, "rcsD"));
modes = xmalloc(sizeof(int) * objectargcount);
names = xmalloc(sizeof(int) * objectargcount);
sizes = xmalloc(sizeof(int) * objectargcount);
// load global symbols and populate page cache
for (i = 0; i < objectargcount; ++i) {
TryAgain:
CHECK_NE(-1, (fd = open(objectargs[i], O_RDONLY)));
CHECK_NE(-1, fstat(fd, st));
CHECK_LT(st->st_size, 0x7ffff000);
if (!st->st_size || S_ISDIR(st->st_mode) ||
endswith(objectargs[i], ".pkg")) {
close(fd);
for (j = i; j + 1 < objectargcount; ++j) {
objectargs[j] = objectargs[j + 1];
}
--objectargcount;
goto TryAgain;
}
names[i] = filenames.i;
sizes[i] = st->st_size;
modes[i] = st->st_mode;
CONCAT(&filenames.p, &filenames.i, &filenames.n, basename(objectargs[i]),
strlen(basename(objectargs[i])));
CONCAT(&filenames.p, &filenames.i, &filenames.n, "/\n", 2);
CHECK_NE(MAP_FAILED,
(elf = mmap(NULL, st->st_size, PROT_READ, MAP_PRIVATE, fd, 0)));
madvise(elf, st->st_size, MADV_WILLNEED);
CHECK(IsElf64Binary(elf, st->st_size));
CHECK_NOTNULL((strs = GetElfStringTable(elf, st->st_size)));
CHECK_NOTNULL((syms = GetElfSymbolTable(elf, st->st_size, &symcount)));
for (j = 0; j < symcount; ++j) {
if (syms[j].st_shndx == SHN_UNDEF) continue;
if (syms[j].st_other == STV_INTERNAL) continue;
if (ELF64_ST_BIND(syms[j].st_info) == STB_LOCAL) continue;
symname = GetElfString(elf, st->st_size, strs, syms[j].st_name);
CONCAT(&symbols.p, &symbols.i, &symbols.n, symname, strlen(symname) + 1);
APPEND(&symnames.p, &symnames.i, &symnames.n, &i);
}
CHECK_NE(-1, munmap(elf, st->st_size));
close(fd);
}
APPEND(&filenames.p, &filenames.i, &filenames.n, "\n");
// compute length of output archive
outsize = 0;
tablebufsize = 4 + symnames.i * 4;
tablebuf = xmalloc(tablebufsize);
offsets = xmalloc(objectargcount * 4);
header1 = xmalloc(sizeof(struct Header));
header2 = xmalloc(sizeof(struct Header));
iov[0].iov_base = "!<arch>\n";
outsize += (iov[0].iov_len = 8);
iov[1].iov_base = header1;
outsize += (iov[1].iov_len = 60);
iov[2].iov_base = tablebuf;
outsize += (iov[2].iov_len = tablebufsize);
iov[3].iov_base = symbols.p;
outsize += (iov[3].iov_len = symbols.i);
iov[4].iov_base = "\n";
outsize += (iov[4].iov_len = outsize & 1);
iov[5].iov_base = header2;
outsize += (iov[5].iov_len = 60);
iov[6].iov_base = filenames.p;
outsize += (iov[6].iov_len = filenames.i);
for (i = 0; i < objectargcount; ++i) {
outsize += outsize & 1;
offsets[i] = outsize;
outsize += 60;
outsize += sizes[i];
}
CHECK_LE(outsize, 0x7ffff000);
// serialize metadata
MakeHeader(header1, "/", -1, 0, tablebufsize + symbols.i);
MakeHeader(header2, "//", -1, 0, filenames.i);
WRITE32BE(tablebuf, symnames.i);
for (i = 0; i < symnames.i; ++i) {
WRITE32BE(tablebuf + 4 + i * 4, offsets[symnames.p[i]]);
}
// write output archive
CHECK_NE(-1, (outfd = open(outpath, O_WRONLY | O_TRUNC | O_CREAT, 0644)));
ftruncate(outfd, outsize);
if ((outsize = writev(outfd, iov, ARRAYLEN(iov))) == -1) goto fail;
for (i = 0; i < objectargcount; ++i) {
if ((fd = open(objectargs[i], O_RDONLY)) == -1) goto fail;
iov[0].iov_base = "\n";
outsize += (iov[0].iov_len = outsize & 1);
iov[1].iov_base = header1;
outsize += (iov[1].iov_len = 60);
MakeHeader(header1, "/", names[i], modes[i], sizes[i]);
if (writev(outfd, iov, 2) == -1) goto fail;
outsize += (remain = sizes[i]);
if (copy_file_range(fd, NULL, outfd, NULL, remain, 0) != remain) goto fail;
close(fd);
}
close(outfd);
free(header2);
free(header1);
free(offsets);
free(tablebuf);
free(sizes);
free(names);
free(modes);
free(symbols.p);
free(filenames.p);
free(symnames.p);
free(st);
return 0;
fail:
err = errno;
if (!err) err = 1;
unlink(outpath);
fputs("error: ar failed\n", stderr);
return err;
}

View File

@ -21,6 +21,7 @@
#include "dsp/tty/tty.h" #include "dsp/tty/tty.h"
#include "libc/alg/arraylist2.h" #include "libc/alg/arraylist2.h"
#include "libc/assert.h" #include "libc/assert.h"
#include "libc/bits/bits.h"
#include "libc/bits/safemacros.h" #include "libc/bits/safemacros.h"
#include "libc/calls/calls.h" #include "libc/calls/calls.h"
#include "libc/calls/ioctl.h" #include "libc/calls/ioctl.h"
@ -165,7 +166,7 @@ FEATURES\n\
struct MemoryView { struct MemoryView {
int64_t start; int64_t start;
unsigned zoom; int zoom;
}; };
struct MachineState { struct MachineState {
@ -1158,10 +1159,17 @@ static void ScrollMemoryView(struct Panel *p, struct MemoryView *v, int64_t a) {
} }
} }
static void ZoomMemoryView(struct MemoryView *v, int dy) { static void ZoomMemoryView(struct MemoryView *v, long y, long x, int dy) {
v->start *= (DUMPWIDTH * (1ull << v->zoom)); long a, b, i, s;
v->zoom = MIN(MAXZOOM, MAX(0, v->zoom + dy)); s = v->start;
v->start /= (DUMPWIDTH * (1ull << v->zoom)); a = v->zoom;
b = MIN(MAXZOOM, MAX(0, a + dy));
i = y * DUMPWIDTH - x;
s *= DUMPWIDTH * (1L << a);
s += i * (1L << a) - i * (1L << b);
s /= DUMPWIDTH * (1L << b);
v->zoom = b;
v->start = s;
} }
static void ScrollMemoryViews(void) { static void ScrollMemoryViews(void) {
@ -1171,15 +1179,15 @@ static void ScrollMemoryViews(void) {
ScrollMemoryView(&pan.stack, &stackview, GetSp()); ScrollMemoryView(&pan.stack, &stackview, GetSp());
} }
static void ZoomMemoryViews(struct Panel *p, int dy) { static void ZoomMemoryViews(struct Panel *p, int y, int x, int dy) {
if (p == &pan.code) { if (p == &pan.code) {
ZoomMemoryView(&codeview, dy); ZoomMemoryView(&codeview, y, x, dy);
} else if (p == &pan.readdata) { } else if (p == &pan.readdata) {
ZoomMemoryView(&readview, dy); ZoomMemoryView(&readview, y, x, dy);
} else if (p == &pan.writedata) { } else if (p == &pan.writedata) {
ZoomMemoryView(&writeview, dy); ZoomMemoryView(&writeview, y, x, dy);
} else if (p == &pan.stack) { } else if (p == &pan.stack) {
ZoomMemoryView(&stackview, dy); ZoomMemoryView(&stackview, y, x, dy);
} }
} }
@ -1798,14 +1806,18 @@ static void OnDiskServiceGetParams(void) {
static void OnDiskServiceReadSectors(void) { static void OnDiskServiceReadSectors(void) {
static int x; static int x;
uint64_t addr, size; uint64_t addr, size;
int64_t drive, head, track, sector, offset; int64_t sectors, drive, head, track, sector, offset;
sectors = m->ax[0];
drive = m->dx[0]; drive = m->dx[0];
head = m->dx[1]; head = m->dx[1];
track = (m->cx[0] & 0b11000000) << 2 | m->cx[1]; track = (m->cx[0] & 0b11000000) << 2 | m->cx[1];
sector = (m->cx[0] & 0b00111111) - 1; sector = (m->cx[0] & 0b00111111) - 1;
offset = head * track * sector * 512; offset = head * track * sector * 512;
size = m->ax[0] * 512; size = sectors * 512;
offset = sector * 512 + track * 512 * 63 + head * 512 * 63 * 1024; offset = sector * 512 + track * 512 * 63 + head * 512 * 63 * 1024;
VERBOSEF("bios read sectors %d "
"@ sector %ld track %ld head %ld drive %ld offset %#lx",
sectors, sector, track, head, drive, offset);
if (0 <= sector && offset + size <= elf->mapsize) { if (0 <= sector && offset + size <= elf->mapsize) {
addr = Read64(m->es) + Read16(m->bx); addr = Read64(m->es) + Read16(m->bx);
if (addr + size <= m->real.n) { if (addr + size <= m->real.n) {
@ -1819,6 +1831,8 @@ static void OnDiskServiceReadSectors(void) {
SetCarry(true); SetCarry(true);
} }
} else { } else {
WARNF("bios read sector failed 0 <= %d && %lx + %lx <= %lx", sector, offset,
size, elf->mapsize);
m->ax[0] = 0x00; m->ax[0] = 0x00;
m->ax[1] = 0x0d; m->ax[1] = 0x0d;
SetCarry(true); SetCarry(true);
@ -2074,7 +2088,9 @@ static void OnBinbase(struct Machine *m) {
} }
static void OnLongBranch(struct Machine *m) { static void OnLongBranch(struct Machine *m) {
if (tuimode) {
Disassemble(); Disassemble();
}
} }
static void OnPageUp(void) { static void OnPageUp(void) {
@ -2098,20 +2114,28 @@ static void SetStatus(const char *fmt, ...) {
setitimer(ITIMER_REAL, &((struct itimerval){{0, 0}, {1, 0}}), NULL); setitimer(ITIMER_REAL, &((struct itimerval){{0, 0}, {1, 0}}), NULL);
} }
static int ClampSpeed(int s) {
return MAX(-0x1000, MIN(0x40000000, s));
}
static void OnTurbo(void) { static void OnTurbo(void) {
if (speed >= -1) { if (!speed || speed == -1) {
speed = MIN(0x40000000, MAX(1, speed) << 1); // 1..40mips skip speed = 1;
} else if (speed > 0) {
speed = ClampSpeed(speed << 1);
} else { } else {
speed >>= 1; speed = ClampSpeed(speed >> 1);
} }
SetStatus("speed %,d", speed); SetStatus("speed %,d", speed);
} }
static void OnSlowmo(void) { static void OnSlowmo(void) {
if (speed > 0) { if (!speed || speed == 1) {
speed >>= 1; speed = -1;
} else if (speed > 0) {
speed = ClampSpeed(speed >> 1);
} else { } else {
speed = MAX(-(5 * 1000), MIN(-1, speed) << 1); // 1ms..5s delay speed = ClampSpeed(speed << 1);
} }
SetStatus("speed %,d", speed); SetStatus("speed %,d", speed);
} }
@ -2221,7 +2245,7 @@ static void Sleep(int ms) {
poll((struct pollfd[]){{ttyin, POLLIN}}, 1, ms); poll((struct pollfd[]){{ttyin, POLLIN}}, 1, ms);
} }
static void OnMouseWheelUp(struct Panel *p) { static void OnMouseWheelUp(struct Panel *p, int y, int x) {
if (p == &pan.disassembly) { if (p == &pan.disassembly) {
opstart -= WHEELDELTA; opstart -= WHEELDELTA;
} else if (p == &pan.code) { } else if (p == &pan.code) {
@ -2241,7 +2265,7 @@ static void OnMouseWheelUp(struct Panel *p) {
} }
} }
static void OnMouseWheelDown(struct Panel *p) { static void OnMouseWheelDown(struct Panel *p, int y, int x) {
if (p == &pan.disassembly) { if (p == &pan.disassembly) {
opstart += WHEELDELTA; opstart += WHEELDELTA;
} else if (p == &pan.code) { } else if (p == &pan.code) {
@ -2261,12 +2285,12 @@ static void OnMouseWheelDown(struct Panel *p) {
} }
} }
static void OnMouseCtrlWheelUp(struct Panel *p) { static void OnMouseCtrlWheelUp(struct Panel *p, int y, int x) {
ZoomMemoryViews(p, -1); ZoomMemoryViews(p, y, x, -1);
} }
static void OnMouseCtrlWheelDown(struct Panel *p) { static void OnMouseCtrlWheelDown(struct Panel *p, int y, int x) {
ZoomMemoryViews(p, +1); ZoomMemoryViews(p, y, x, +1);
} }
static struct Panel *LocatePanel(int y, int x) { static struct Panel *LocatePanel(int y, int x) {
@ -2290,18 +2314,20 @@ static void OnMouse(char *p) {
y = min(tyn, max(1, strtol(p, &p, 10))) - 1; y = min(tyn, max(1, strtol(p, &p, 10))) - 1;
e |= (*p == 'm') << 2; e |= (*p == 'm') << 2;
if ((ep = LocatePanel(y, x))) { if ((ep = LocatePanel(y, x))) {
y -= ep->top;
x -= ep->left;
switch (e) { switch (e) {
case kMouseWheelUp: case kMouseWheelUp:
OnMouseWheelUp(ep); OnMouseWheelUp(ep, y, x);
break; break;
case kMouseWheelDown: case kMouseWheelDown:
OnMouseWheelDown(ep); OnMouseWheelDown(ep, y, x);
break; break;
case kMouseCtrlWheelUp: case kMouseCtrlWheelUp:
OnMouseCtrlWheelUp(ep); OnMouseCtrlWheelUp(ep, y, x);
break; break;
case kMouseCtrlWheelDown: case kMouseCtrlWheelDown:
OnMouseCtrlWheelDown(ep); OnMouseCtrlWheelDown(ep, y, x);
break; break;
default: default:
break; break;

View File

@ -0,0 +1,55 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/calls/calls.h"
#include "libc/errno.h"
#include "libc/log/check.h"
#include "libc/runtime/runtime.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/o.h"
/**
* Removes file system caches from RAM.
*
* make o//tool/build/dropcache.com
* sudo mv o//tool/build/dropcache.com /usr/local/bin/
* sudo chown root /usr/local/bin/dropcache.com
* sudo chmod u+s /usr/local/bin/dropcache.com
*/
static void Write(int fd, const char *s) {
write(fd, s, strlen(s));
}
int main(int argc, char *argv[]) {
int fd;
sync();
fd = open("/proc/sys/vm/drop_caches", O_WRONLY);
if (fd == -1) {
if (errno == EACCES) {
Write(1, "error: need root privileges\n");
} else if (errno == ENOENT) {
Write(1, "error: need /proc filesystem\n");
}
exit(1);
}
Write(fd, "3\n");
close(fd);
return 0;
}

View File

@ -74,8 +74,8 @@ static void DisLoadElfSyms(struct Dis *d, struct Elf *elf) {
const Elf64_Sym *st, *sym; const Elf64_Sym *st, *sym;
bool isabs, iscode, isweak, islocal, ishidden, isprotected, isfunc, isobject; bool isabs, iscode, isweak, islocal, ishidden, isprotected, isfunc, isobject;
j = 0; j = 0;
if ((d->syms.stab = getelfstringtable(elf->ehdr, elf->size)) && if ((d->syms.stab = GetElfStringTable(elf->ehdr, elf->size)) &&
(st = getelfsymboltable(elf->ehdr, elf->size, &n))) { (st = GetElfSymbolTable(elf->ehdr, elf->size, &n))) {
stablen = (intptr_t)elf->ehdr + elf->size - (intptr_t)d->syms.stab; stablen = (intptr_t)elf->ehdr + elf->size - (intptr_t)d->syms.stab;
if (d->syms.n < n) { if (d->syms.n < n) {
d->syms.n = n; d->syms.n = n;

View File

@ -238,8 +238,8 @@ const char *DisSpecMap0(struct XedDecodedInst *x, char *p) {
RCASE(0xCB, "lret"); RCASE(0xCB, "lret");
RCASE(0xCC, "int3"); RCASE(0xCC, "int3");
RCASE(0xCD, "int Ib"); RCASE(0xCD, "int Ib");
RCASE(0xD0, "BIT Eb $1"); RCASE(0xD0, "BIT Eb");
RCASE(0xD1, "BIT Evqp $1"); RCASE(0xD1, "BIT Evqp");
RCASE(0xD2, "BIT Evqp %cl"); RCASE(0xD2, "BIT Evqp %cl");
RCASE(0xD3, "BIT Evqp %cl"); RCASE(0xD3, "BIT Evqp %cl");
RCASE(0xD4, x->op.uimm0 == 0x0a ? "aam" : "aam Ib"); RCASE(0xD4, x->op.uimm0 == 0x0a ? "aam" : "aam Ib");

View File

@ -178,7 +178,7 @@ struct ElfWriter *elfwriter_open(const char *path, int mode) {
void elfwriter_close(struct ElfWriter *elf) { void elfwriter_close(struct ElfWriter *elf) {
size_t i; size_t i;
FlushTables(elf); FlushTables(elf);
CHECK_NE(-1, msync(elf->map, elf->wrote, MS_SYNC)); CHECK_NE(-1, msync(elf->map, elf->wrote, MS_ASYNC));
CHECK_NE(-1, munmap(elf->map, elf->mapsize)); CHECK_NE(-1, munmap(elf->map, elf->mapsize));
CHECK_NE(-1, ftruncate(elf->fd, elf->wrote)); CHECK_NE(-1, ftruncate(elf->fd, elf->wrote));
CHECK_NE(-1, close(elf->fd)); CHECK_NE(-1, close(elf->fd));

View File

@ -137,40 +137,24 @@ void LoadProgram(struct Machine *m, const char *prog, char **args, char **vars,
int fd; int fd;
ssize_t rc; ssize_t rc;
int64_t sp; int64_t sp;
char *real;
void *stack;
struct stat st; struct stat st;
size_t i, codesize, mappedsize, extrasize; size_t i, mappedsize;
DCHECK_NOTNULL(prog); DCHECK_NOTNULL(prog);
elf->prog = prog; elf->prog = prog;
if ((fd = open(prog, O_RDONLY)) == -1 || if ((fd = open(prog, O_RDONLY)) == -1 ||
(fstat(fd, &st) == -1 || !st.st_size) /* || !S_ISREG(st.st_mode) */) { (fstat(fd, &st) == -1 || !st.st_size)) {
fputs(prog, stderr); fputs(prog, stderr);
fputs(": not found\n", stderr); fputs(": not found\n", stderr);
exit(1); exit(1);
} }
codesize = st.st_size; elf->mapsize = st.st_size;
elf->mapsize = ROUNDDOWN(codesize, FRAMESIZE);
extrasize = codesize - elf->mapsize;
elf->map = real = (char *)0x0000400000000000;
if (elf->mapsize) {
CHECK_NE(MAP_FAILED, mmap(real, elf->mapsize, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_FIXED, fd, 0));
real += elf->mapsize;
}
if (extrasize) {
CHECK_NE(MAP_FAILED, CHECK_NE(MAP_FAILED,
mmap(real, ROUNDUP(extrasize, FRAMESIZE), PROT_READ | PROT_WRITE, (elf->map = mmap(NULL, elf->mapsize, PROT_READ | PROT_WRITE,
MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0)); MAP_PRIVATE, fd, 0)));
for (i = 0; i < extrasize; i += (size_t)rc) {
CHECK_NE(-1, (rc = pread(fd, real + i, extrasize - i, elf->mapsize + i)));
}
elf->mapsize += ROUNDUP(extrasize, FRAMESIZE);
}
CHECK_NE(-1, close(fd)); CHECK_NE(-1, close(fd));
ResetCpu(m); ResetCpu(m);
if ((m->mode & 3) == XED_MODE_REAL) { if ((m->mode & 3) == XED_MODE_REAL) {
BootProgram(m, elf, codesize); BootProgram(m, elf, elf->mapsize);
} else { } else {
sp = 0x800000000000; sp = 0x800000000000;
Write64(m->sp, sp); Write64(m->sp, sp);
@ -179,13 +163,13 @@ void LoadProgram(struct Machine *m, const char *prog, char **args, char **vars,
LoadArgv(m, prog, args, vars); LoadArgv(m, prog, args, vars);
if (memcmp(elf->map, "\177ELF", 4) == 0) { if (memcmp(elf->map, "\177ELF", 4) == 0) {
elf->ehdr = (void *)elf->map; elf->ehdr = (void *)elf->map;
elf->size = codesize; elf->size = elf->mapsize;
LoadElf(m, elf); LoadElf(m, elf);
} else { } else {
elf->base = IMAGE_BASE_VIRTUAL; elf->base = IMAGE_BASE_VIRTUAL;
elf->ehdr = NULL; elf->ehdr = NULL;
elf->size = 0; elf->size = 0;
LoadBin(m, elf->base, prog, elf->map, codesize); LoadBin(m, elf->base, prog, elf->map, elf->mapsize);
} }
} }
} }

View File

@ -109,24 +109,24 @@ struct Packages {
struct Package { struct Package {
uint32_t magic; uint32_t magic;
int32_t abi; int32_t abi;
uint32_t path; /* pkg->strings.p[path] */ uint32_t path; // pkg->strings.p[path]
int64_t fd; /* not persisted */ int64_t fd; // not persisted
void *addr; /* not persisted */ void *addr; // not persisted
size_t size; /* not persisted */ size_t size; // not persisted
struct Strings { struct Strings {
size_t i, n; size_t i, n;
char *p; /* persisted as pkg+RVA */ char *p; // persisted as pkg+RVA
} strings; /* TODO(jart): interning? */ } strings; // TODO(jart): interning?
struct Objects { struct Objects {
size_t i, n; size_t i, n;
struct Object { struct Object {
uint32_t path; /* pkg->strings.p[path] */ uint32_t path; // pkg->strings.p[path]
int64_t fd; /* not persisted */ unsigned mode; // not persisted
struct Elf64_Ehdr *elf; /* not persisted */ struct Elf64_Ehdr *elf; // not persisted
size_t size; /* not persisted */ size_t size; // not persisted
char *strs; /* not persisted */ char *strs; // not persisted
Elf64_Sym *syms; /* not persisted */ Elf64_Sym *syms; // not persisted
Elf64_Xword symcount; /* not persisted */ Elf64_Xword symcount; // not persisted
struct Sections { struct Sections {
size_t i, n; size_t i, n;
struct Section { struct Section {
@ -149,20 +149,20 @@ struct Packages {
} * p; } * p;
} ops; } ops;
} * p; } * p;
} sections; /* not persisted */ } sections; // not persisted
} * p; /* persisted as pkg+RVA */ } * p; // persisted as pkg+RVA
} objects; } objects;
struct Symbols { struct Symbols {
size_t i, n; size_t i, n;
struct Symbol { struct Symbol {
uint32_t name; /* pkg->strings.p[name] */ uint32_t name; // pkg->strings.p[name]
enum SectionKind kind : 8; enum SectionKind kind : 8;
uint8_t bind : 4; uint8_t bind : 4;
uint8_t type : 4; uint8_t type : 4;
uint16_t object; /* pkg->objects.p[object] */ uint16_t object; // pkg->objects.p[object]
} * p; /* persisted as pkg+RVA */ } * p; // persisted as pkg+RVA
} symbols, undefs; /* TODO(jart): hash undefs? */ } symbols, undefs; // TODO(jart): hash undefs?
} * *p; /* persisted across multiple files */ } * *p; // persisted across multiple files
}; };
int CompareSymbolName(const struct Symbol *a, const struct Symbol *b, int CompareSymbolName(const struct Symbol *a, const struct Symbol *b,
@ -265,7 +265,7 @@ void IndexSections(struct Object *obj) {
memset(&sect, 0, sizeof(sect)); memset(&sect, 0, sizeof(sect));
CHECK_NOTNULL((shdr = getelfsectionheaderaddress(obj->elf, obj->size, i))); CHECK_NOTNULL((shdr = getelfsectionheaderaddress(obj->elf, obj->size, i)));
if (shdr->sh_type != SHT_NULL) { if (shdr->sh_type != SHT_NULL) {
CHECK_NOTNULL((name = getelfsectionname(obj->elf, obj->size, shdr))); CHECK_NOTNULL((name = GetElfSectionName(obj->elf, obj->size, shdr)));
if (startswith(name, ".sort.")) name += 5; if (startswith(name, ".sort.")) name += 5;
if ((strcmp(name, ".piro.relo") == 0 || if ((strcmp(name, ".piro.relo") == 0 ||
startswith(name, ".piro.relo.")) || startswith(name, ".piro.relo.")) ||
@ -329,7 +329,7 @@ void LoadSymbols(struct Package *pkg, uint32_t object) {
if (symbol.bind != STB_LOCAL && if (symbol.bind != STB_LOCAL &&
(symbol.type == STT_OBJECT || symbol.type == STT_FUNC || (symbol.type == STT_OBJECT || symbol.type == STT_FUNC ||
symbol.type == STT_COMMON || symbol.type == STT_NOTYPE)) { symbol.type == STT_COMMON || symbol.type == STT_NOTYPE)) {
name = getelfstring(obj->elf, obj->size, obj->strs, obj->syms[i].st_name); name = GetElfString(obj->elf, obj->size, obj->strs, obj->syms[i].st_name);
DEBUGF("%s", name); DEBUGF("%s", name);
if (strcmp(name, "_GLOBAL_OFFSET_TABLE_") != 0) { if (strcmp(name, "_GLOBAL_OFFSET_TABLE_") != 0) {
symbol.kind = ClassifySection(obj, symbol.type, obj->syms[i].st_shndx); symbol.kind = ClassifySection(obj, symbol.type, obj->syms[i].st_shndx);
@ -347,23 +347,25 @@ void OpenObject(struct Package *pkg, struct Object *obj, int mode, int prot,
int flags) { int flags) {
int fd; int fd;
struct stat st; struct stat st;
CHECK_NE(-1, (fd = open(&pkg->strings.p[obj->path], mode)), "path=%`'s", CHECK_NE(-1, (fd = open(&pkg->strings.p[obj->path], (obj->mode = mode))),
&pkg->strings.p[obj->path]); "path=%`'s", &pkg->strings.p[obj->path]);
CHECK_NE(-1, fstat(fd, &st)); CHECK_NE(-1, fstat(fd, &st));
CHECK_NE(MAP_FAILED, (obj->elf = mmap(NULL, (obj->size = st.st_size), prot, CHECK_NE(MAP_FAILED, (obj->elf = mmap(NULL, (obj->size = st.st_size), prot,
flags, fd, 0))); flags, fd, 0)));
CHECK_NE(-1, close(fd)); CHECK_NE(-1, close(fd));
CHECK(iself64binary(obj->elf, obj->size), "path=%`'s", CHECK(IsElf64Binary(obj->elf, obj->size), "path=%`'s",
&pkg->strings.p[obj->path]); &pkg->strings.p[obj->path]);
CHECK_NOTNULL((obj->strs = getelfstringtable(obj->elf, obj->size))); CHECK_NOTNULL((obj->strs = GetElfStringTable(obj->elf, obj->size)));
CHECK_NOTNULL( CHECK_NOTNULL(
(obj->syms = getelfsymboltable(obj->elf, obj->size, &obj->symcount))); (obj->syms = GetElfSymbolTable(obj->elf, obj->size, &obj->symcount)));
CHECK_NE(0, obj->symcount); CHECK_NE(0, obj->symcount);
IndexSections(obj); IndexSections(obj);
} }
void CloseObject(struct Object *obj) { void CloseObject(struct Object *obj) {
msync(obj->elf, obj->size, MS_SYNC); if ((obj->mode & O_ACCMODE) != O_RDONLY) {
CHECK_NE(-1, msync(obj->elf, obj->size, MS_ASYNC | MS_INVALIDATE));
}
CHECK_NE(-1, munmap(obj->elf, obj->size)); CHECK_NE(-1, munmap(obj->elf, obj->size));
} }
@ -477,7 +479,7 @@ void OptimizeRelocations(struct Package *pkg, struct Packages *deps,
if ((ELF64_R_TYPE(rela->r_info) == R_X86_64_PC32 || if ((ELF64_R_TYPE(rela->r_info) == R_X86_64_PC32 ||
ELF64_R_TYPE(rela->r_info) == R_X86_64_GOTPCREL) && ELF64_R_TYPE(rela->r_info) == R_X86_64_GOTPCREL) &&
FindSymbol( FindSymbol(
getelfstring(obj->elf, obj->size, obj->strs, GetElfString(obj->elf, obj->size, obj->strs,
obj->syms[ELF64_R_SYM(rela->r_info)].st_name), obj->syms[ELF64_R_SYM(rela->r_info)].st_name),
pkg, deps, &refpkg, &refsym) && pkg, deps, &refpkg, &refsym) &&
(refsym->kind == kData || refsym->kind == kBss) && (refsym->kind == kData || refsym->kind == kBss) &&
@ -500,7 +502,7 @@ void OptimizeRelocations(struct Package *pkg, struct Packages *deps,
* Then libc/runtime/ftrace.greg.c morphs it back at runtime. * Then libc/runtime/ftrace.greg.c morphs it back at runtime.
*/ */
if (ELF64_R_TYPE(rela->r_info) == R_X86_64_GOTPCRELX && if (ELF64_R_TYPE(rela->r_info) == R_X86_64_GOTPCRELX &&
strcmp(getelfstring(obj->elf, obj->size, obj->strs, strcmp(GetElfString(obj->elf, obj->size, obj->strs,
obj->syms[ELF64_R_SYM(rela->r_info)].st_name), obj->syms[ELF64_R_SYM(rela->r_info)].st_name),
"mcount") == 0) { "mcount") == 0) {
rela->r_info = R_X86_64_NONE; rela->r_info = R_X86_64_NONE;
@ -518,7 +520,7 @@ void OptimizeRelocations(struct Package *pkg, struct Packages *deps,
*/ */
if ((ELF64_R_TYPE(rela->r_info) == R_X86_64_PC32 || if ((ELF64_R_TYPE(rela->r_info) == R_X86_64_PC32 ||
ELF64_R_TYPE(rela->r_info) == R_X86_64_PLT32) && ELF64_R_TYPE(rela->r_info) == R_X86_64_PLT32) &&
strcmp(getelfstring(obj->elf, obj->size, obj->strs, strcmp(GetElfString(obj->elf, obj->size, obj->strs,
obj->syms[ELF64_R_SYM(rela->r_info)].st_name), obj->syms[ELF64_R_SYM(rela->r_info)].st_name),
"mcount") == 0) { "mcount") == 0) {
rela->r_info = R_X86_64_NONE; rela->r_info = R_X86_64_NONE;
@ -598,7 +600,7 @@ void CompressLowEntropyReadOnlyDataSections(struct Package *pkg,
!(shdr->sh_flags & !(shdr->sh_flags &
(SHF_WRITE | SHF_MERGE | SHF_STRINGS | SHF_COMPRESSED))) && (SHF_WRITE | SHF_MERGE | SHF_STRINGS | SHF_COMPRESSED))) &&
(p = getelfsectionaddress(obj->elf, obj->size, shdr)) && (p = getelfsectionaddress(obj->elf, obj->size, shdr)) &&
startswith((name = getelfsectionname(obj->elf, obj->size, shdr)), startswith((name = GetElfSectionName(obj->elf, obj->size, shdr)),
".rodata") && ".rodata") &&
rlencode(&rle, p, shdr->sh_size) != -1) { rlencode(&rle, p, shdr->sh_size) != -1) {
isprofitable = rle.i * sizeof(rle.p[0]) <= shdr->sh_size / 2; isprofitable = rle.i * sizeof(rle.p[0]) <= shdr->sh_size / 2;

View File

@ -312,6 +312,7 @@ void zipobj(int argc, char **argv) {
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
showcrashreports();
zipobj(argc, argv); zipobj(argc, argv);
return 0; return 0;
} }

146
tool/decode/ar.c 100644
View File

@ -0,0 +1,146 @@
/*-*- 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
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
*/
#include "libc/bits/bits.h"
#include "libc/calls/calls.h"
#include "libc/calls/struct/stat.h"
#include "libc/conv/conv.h"
#include "libc/log/check.h"
#include "libc/log/log.h"
#include "libc/mem/mem.h"
#include "libc/runtime/runtime.h"
#include "libc/stdio/stdio.h"
#include "libc/str/str.h"
#include "libc/sysv/consts/map.h"
#include "libc/sysv/consts/o.h"
#include "libc/sysv/consts/prot.h"
#include "libc/x/x.h"
#define AR_MAGIC1 "!<arch>\n"
#define AR_MAGIC2 "`\n"
/**
* ar rU doge.a NOTICE # create archive and use non-deterministic stuff
* o//tool/decode/ar.com doge.a
*/
static int fd;
static uint8_t *data;
static long size;
static const char *path;
static struct stat st;
static void PrintString(uint8_t *p, long n, const char *name) {
char *s;
s = xmalloc(n + 1);
s[n] = '\0';
memcpy(s, p, n);
printf("\t.ascii\t%`'.*s\t\t\t# %s\n", n, s, name);
free(s);
}
static void Open(void) {
if ((fd = open(path, O_RDONLY)) == -1) {
fprintf(stderr, "error: open() failed: %s\n", path);
exit(1);
}
CHECK_NE(-1, fstat(fd, &st));
if (!(size = st.st_size)) exit(0);
CHECK_NE(MAP_FAILED,
(data = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0)));
LOGIFNEG1(close(fd));
}
static void Close(void) {
LOGIFNEG1(munmap(data, size));
}
static void Check(void) {
if (size < 8 + 60 + 4 ||
(memcmp(data, AR_MAGIC1, strlen(AR_MAGIC1)) != 0 ||
memcmp(data + 66, AR_MAGIC2, strlen(AR_MAGIC2)) != 0)) {
fprintf(stderr, "error: not a unix archive: %s\n", path);
exit(1);
}
}
static void PrintTable(void) {
}
static void PrintHeader(uint8_t *p) {
PrintString(p + 0, 16, "file identifier [ascii]");
PrintString(p + 16, 12, "file modification timestamp [decimal]");
PrintString(p + 28, 6, "owner id [decimal]");
PrintString(p + 34, 6, "group id [decimal]");
PrintString(p + 40, 8, "file mode [octal] (type and permission)");
PrintString(p + 48, 10, "file size in bytes [decimal]");
PrintString(p + 58, 2, "ending characters");
}
static void Print(void) {
int arsize;
uint8_t *b, *p;
uint64_t offset;
uint32_t i, n, o, table, entries, symbols, symbolslen;
arsize = atoi((char *)(data + 8 + 48));
CHECK_LE(4, arsize);
CHECK_LE(8 + 60 + arsize, size);
entries = read32be(data + 8 + 60);
CHECK_LE(4 + entries * 4 + 1, arsize);
printf("\t# %'s\n", path);
PrintString(data, 8, "file signature");
PrintHeader(data + 8);
printf("\n");
printf("\t.long\t%u\t\t\t# %s\n", entries, "symbol table entries");
table = 8 + 60 + 4;
for (i = 0; i < entries; ++i) {
printf("\t.long\t%#x\t\t\t\t# %u\n", read32be(data + table + i * 4), i);
}
symbols = table + entries * 4;
symbolslen = arsize - (4 + entries * 4);
for (i = o = 0; o < symbolslen; ++i, o += n + 1) {
b = data + symbols + o;
CHECK_NOTNULL((p = memchr(b, '\0', symbolslen - (symbols + o))));
n = p - b;
printf("\t.asciz\t%#`'.*s\t\t\t# %u\n", n, b, i);
}
offset = 8 + 60 + arsize;
while (offset < size) {
offset += offset & 1;
CHECK_LE(offset + 60, size);
CHECK_EQ(0, memcmp(data + offset + 58, AR_MAGIC2, strlen(AR_MAGIC2)));
arsize = atoi((char *)(data + offset + 48));
CHECK_LE(offset + 60 + arsize, size);
printf("\n");
PrintHeader(data + offset);
offset += 60 + arsize;
}
}
int main(int argc, char *argv[]) {
if (argc < 2) return 1;
path = argv[1];
Open();
Check();
Print();
Close();
return 0;
}

View File

@ -134,8 +134,8 @@ static void printelfsectionheader(int i, char *shstrtab) {
printf(".Lsh%d:", i); printf(".Lsh%d:", i);
show(".long", format(b1, "%d", shdr->sh_name), show(".long", format(b1, "%d", shdr->sh_name),
format(b2, format(b2,
"%`'s == getelfstring(elf, st->st_size, shstrtab, shdr->sh_name)", "%`'s == GetElfString(elf, st->st_size, shstrtab, shdr->sh_name)",
getelfstring(elf, st->st_size, shstrtab, shdr->sh_name))); GetElfString(elf, st->st_size, shstrtab, shdr->sh_name)));
show(".long", show(".long",
firstnonnull(findnamebyid(kElfSectionTypeNames, shdr->sh_type), firstnonnull(findnamebyid(kElfSectionTypeNames, shdr->sh_type),
format(b1, "%d", shdr->sh_type)), format(b1, "%d", shdr->sh_type)),
@ -167,7 +167,7 @@ static void printelfsectionheaders(void) {
->sh_offset); ->sh_offset);
for (i = 0; i < elf->e_shnum; ++i) { for (i = 0; i < elf->e_shnum; ++i) {
Elf64_Shdr *shdr = getelfsectionheaderaddress(elf, st->st_size, i); Elf64_Shdr *shdr = getelfsectionheaderaddress(elf, st->st_size, i);
const char *str = getelfstring(elf, st->st_size, shstrtab, shdr->sh_name); const char *str = GetElfString(elf, st->st_size, shstrtab, shdr->sh_name);
show(".asciz", format(b1, "%`'s", str), NULL); show(".asciz", format(b1, "%`'s", str), NULL);
} }
} }
@ -199,14 +199,14 @@ static void printelfsymbolother(Elf64_Sym *sym) {
static void printelfsymbol(Elf64_Sym *sym, char *strtab, char *shstrtab) { static void printelfsymbol(Elf64_Sym *sym, char *strtab, char *shstrtab) {
show(".long", format(b1, "%d", sym->st_name), show(".long", format(b1, "%d", sym->st_name),
format(b2, "%`'s (sym->st_name)", format(b2, "%`'s (sym->st_name)",
getelfstring(elf, st->st_size, strtab, sym->st_name))); GetElfString(elf, st->st_size, strtab, sym->st_name)));
printelfsymbolinfo(sym); printelfsymbolinfo(sym);
printelfsymbolother(sym); printelfsymbolother(sym);
show(".short", format(b1, "%d", sym->st_shndx), show(".short", format(b1, "%d", sym->st_shndx),
format(b2, "%s sym->st_shndx", format(b2, "%s sym->st_shndx",
sym->st_shndx < 0xff00 sym->st_shndx < 0xff00
? format(b1, "%`'s", ? format(b1, "%`'s",
getelfstring(elf, st->st_size, shstrtab, GetElfString(elf, st->st_size, shstrtab,
getelfsectionheaderaddress( getelfsectionheaderaddress(
elf, st->st_size, sym->st_shndx) elf, st->st_size, sym->st_shndx)
->sh_name)) ->sh_name))
@ -217,8 +217,8 @@ static void printelfsymbol(Elf64_Sym *sym, char *strtab, char *shstrtab) {
static void printelfsymboltable(void) { static void printelfsymboltable(void) {
size_t i, symcount = 0; size_t i, symcount = 0;
Elf64_Sym *symtab = getelfsymboltable(elf, st->st_size, &symcount); Elf64_Sym *symtab = GetElfSymbolTable(elf, st->st_size, &symcount);
char *strtab = getelfstringtable(elf, st->st_size); char *strtab = GetElfStringTable(elf, st->st_size);
char *shstrtab = getelfsectionnamestringtable(elf, st->st_size); char *shstrtab = getelfsectionnamestringtable(elf, st->st_size);
if (symtab && strtab) { if (symtab && strtab) {
printf("\n\n"); printf("\n\n");
@ -239,8 +239,8 @@ static char *getelfsymbolname(const Elf64_Ehdr *elf, size_t mapsize,
((shstrtab && !sym->st_name && ((shstrtab && !sym->st_name &&
ELF64_ST_TYPE(sym->st_info) == STT_SECTION && ELF64_ST_TYPE(sym->st_info) == STT_SECTION &&
(shdr = getelfsectionheaderaddress(elf, mapsize, sym->st_shndx)) && (shdr = getelfsectionheaderaddress(elf, mapsize, sym->st_shndx)) &&
(res = getelfstring(elf, mapsize, shstrtab, shdr->sh_name))) || (res = GetElfString(elf, mapsize, shstrtab, shdr->sh_name))) ||
(strtab && (res = getelfstring(elf, mapsize, strtab, sym->st_name))))) { (strtab && (res = GetElfString(elf, mapsize, strtab, sym->st_name))))) {
return res; return res;
} else { } else {
return NULL; return NULL;
@ -254,13 +254,13 @@ static void printelfrelocations(void) {
const Elf64_Rela *rela; const Elf64_Rela *rela;
const Elf64_Shdr *shdr, *boop; const Elf64_Shdr *shdr, *boop;
char *strtab, *shstrtab, *symbolname; char *strtab, *shstrtab, *symbolname;
strtab = getelfstringtable(elf, st->st_size); strtab = GetElfStringTable(elf, st->st_size);
shstrtab = getelfsectionnamestringtable(elf, st->st_size); shstrtab = getelfsectionnamestringtable(elf, st->st_size);
for (i = 0; i < elf->e_shnum; ++i) { for (i = 0; i < elf->e_shnum; ++i) {
if ((shdr = getelfsectionheaderaddress(elf, st->st_size, i)) && if ((shdr = getelfsectionheaderaddress(elf, st->st_size, i)) &&
shdr->sh_type == SHT_RELA && shdr->sh_type == SHT_RELA &&
(rela = getelfsectionaddress(elf, st->st_size, shdr))) { (rela = getelfsectionaddress(elf, st->st_size, shdr))) {
printf("\n/\t%s\n", getelfsectionname(elf, st->st_size, shdr)); printf("\n/\t%s\n", GetElfSectionName(elf, st->st_size, shdr));
printf("\t.org\t%#x\n", (intptr_t)rela - (intptr_t)elf); printf("\t.org\t%#x\n", (intptr_t)rela - (intptr_t)elf);
for (j = 0; ((uintptr_t)rela + sizeof(Elf64_Rela) <= for (j = 0; ((uintptr_t)rela + sizeof(Elf64_Rela) <=
min((uintptr_t)elf + st->st_size, min((uintptr_t)elf + st->st_size,
@ -272,7 +272,7 @@ static void printelfrelocations(void) {
symbolname = symbolname =
getelfsymbolname(elf, st->st_size, strtab, shstrtab, &syms[sym]); getelfsymbolname(elf, st->st_size, strtab, shstrtab, &syms[sym]);
printf("/\t%s+%#lx → %s%c%#lx\n", printf("/\t%s+%#lx → %s%c%#lx\n",
getelfstring( GetElfString(
elf, st->st_size, shstrtab, elf, st->st_size, shstrtab,
getelfsectionheaderaddress(elf, st->st_size, shdr->sh_info) getelfsectionheaderaddress(elf, st->st_size, shdr->sh_info)
->sh_name), ->sh_name),

View File

@ -68,6 +68,6 @@ kPollNames:
lodsl lodsl
add %rbx,%rax # %rbx is image base (cosmo abi) add %rbx,%rax # %rbx is image base (cosmo abi)
stosq stosq
loop 0b .loop 0b
add $16,%rdi add $16,%rdi
.init.end 301,_init_kPollNames .init.end 301,_init_kPollNames