mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-15 15:20:02 +00:00
Add support for symbol table in .com files
This change fixes minor bugs and adds a feature, which lets us store the ELF symbol table, inside the ZIP directory. We use the path /zip/.symtab which can be safely removed using a zip editing tool, to make the binary smaller after compilation. This supplements the existing method of using a separate .com.dbg file, which is still supported. The intent is people don't always know that it's a good idea to download the debug file. It's not great having someone's first experience be a crash report, that only has numbers rather than symbols. This will help fix that!
This commit is contained in:
parent
393ca4be40
commit
23b72eb617
61 changed files with 963 additions and 510 deletions
|
@ -41,8 +41,8 @@ textwindows int sys_getrusage_nt(int who, struct rusage *usage) {
|
|||
if ((who == RUSAGE_SELF ? GetProcessTimes : GetThreadTimes)(
|
||||
(who == RUSAGE_SELF ? GetCurrentProcess : GetCurrentThread)(),
|
||||
&CreationFileTime, &ExitFileTime, &KernelFileTime, &UserFileTime)) {
|
||||
usage->ru_utime = FileTimeToTimeVal(UserFileTime);
|
||||
usage->ru_stime = FileTimeToTimeVal(KernelFileTime);
|
||||
usage->ru_utime = WindowsDurationToTimeVal(ReadFileTime(UserFileTime));
|
||||
usage->ru_stime = WindowsDurationToTimeVal(ReadFileTime(KernelFileTime));
|
||||
} else {
|
||||
return __winerr();
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
@ -29,11 +30,16 @@
|
|||
* @return 0 on success, or -1 w/ errno
|
||||
*/
|
||||
int getrusage(int who, struct rusage *usage) {
|
||||
if (who == 99) return einval();
|
||||
if (IsAsan() && !__asan_is_valid(usage, sizeof(*usage))) return efault();
|
||||
if (!IsWindows()) {
|
||||
return sys_getrusage(who, usage);
|
||||
int rc;
|
||||
if (who == 99) {
|
||||
rc = einval();
|
||||
} else if (IsAsan() && !__asan_is_valid(usage, sizeof(*usage))) {
|
||||
rc = efault();
|
||||
} else if (!IsWindows()) {
|
||||
rc = sys_getrusage(who, usage);
|
||||
} else {
|
||||
return sys_getrusage_nt(who, usage);
|
||||
rc = sys_getrusage_nt(who, usage);
|
||||
}
|
||||
STRACE("getrusage(%d, %p) → %d% m", who, usage, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -31,41 +31,47 @@
|
|||
#include "libc/sysv/errfuns.h"
|
||||
|
||||
textwindows int ioctl_tiocgwinsz_nt(struct Fd *fd, struct winsize *ws) {
|
||||
int i;
|
||||
int i, e;
|
||||
uint32_t mode;
|
||||
struct Fd *fds[3];
|
||||
struct NtStartupInfo startinfo;
|
||||
struct NtConsoleScreenBufferInfoEx sbinfo;
|
||||
if (!ws) return efault();
|
||||
fds[0] = fd, fds[1] = g_fds.p + 1, fds[2] = g_fds.p + 0;
|
||||
GetStartupInfo(&startinfo);
|
||||
for (i = 0; i < ARRAYLEN(fds); ++i) {
|
||||
if (fds[i]->kind == kFdFile || fds[i]->kind == kFdConsole) {
|
||||
if (GetConsoleMode(fds[i]->handle, &mode)) {
|
||||
bzero(&sbinfo, sizeof(sbinfo));
|
||||
sbinfo.cbSize = sizeof(sbinfo);
|
||||
if (GetConsoleScreenBufferInfoEx(fds[i]->handle, &sbinfo)) {
|
||||
ws->ws_col = sbinfo.srWindow.Right - sbinfo.srWindow.Left + 1;
|
||||
ws->ws_row = sbinfo.srWindow.Bottom - sbinfo.srWindow.Top + 1;
|
||||
ws->ws_xpixel = 0;
|
||||
ws->ws_ypixel = 0;
|
||||
return 0;
|
||||
} else if (startinfo.dwFlags & kNtStartfUsecountchars) {
|
||||
ws->ws_col = startinfo.dwXCountChars;
|
||||
ws->ws_row = startinfo.dwYCountChars;
|
||||
ws->ws_xpixel = 0;
|
||||
ws->ws_ypixel = 0;
|
||||
return 0;
|
||||
e = errno;
|
||||
if (ws) {
|
||||
fds[0] = fd, fds[1] = g_fds.p + 1, fds[2] = g_fds.p + 0;
|
||||
GetStartupInfo(&startinfo);
|
||||
for (i = 0; i < ARRAYLEN(fds); ++i) {
|
||||
if (fds[i]->kind == kFdFile || fds[i]->kind == kFdConsole) {
|
||||
if (GetConsoleMode(fds[i]->handle, &mode)) {
|
||||
bzero(&sbinfo, sizeof(sbinfo));
|
||||
sbinfo.cbSize = sizeof(sbinfo);
|
||||
if (GetConsoleScreenBufferInfoEx(fds[i]->handle, &sbinfo)) {
|
||||
ws->ws_col = sbinfo.srWindow.Right - sbinfo.srWindow.Left + 1;
|
||||
ws->ws_row = sbinfo.srWindow.Bottom - sbinfo.srWindow.Top + 1;
|
||||
ws->ws_xpixel = 0;
|
||||
ws->ws_ypixel = 0;
|
||||
errno = e;
|
||||
return 0;
|
||||
} else if (startinfo.dwFlags & kNtStartfUsecountchars) {
|
||||
ws->ws_col = startinfo.dwXCountChars;
|
||||
ws->ws_row = startinfo.dwYCountChars;
|
||||
ws->ws_xpixel = 0;
|
||||
ws->ws_ypixel = 0;
|
||||
errno = e;
|
||||
return 0;
|
||||
} else {
|
||||
__winerr();
|
||||
}
|
||||
} else {
|
||||
__winerr();
|
||||
STRACE("%s() failed %m", "GetConsoleMode");
|
||||
enotty();
|
||||
}
|
||||
} else {
|
||||
STRACE("%s() failed %m", "GetConsoleMode");
|
||||
enotty();
|
||||
ebadf();
|
||||
}
|
||||
} else {
|
||||
ebadf();
|
||||
}
|
||||
} else {
|
||||
efault();
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/log/libfatal.internal.h"
|
||||
#include "libc/macros.internal.h"
|
||||
#include "libc/mem/alloca.h"
|
||||
|
@ -42,22 +43,6 @@
|
|||
#define KERN_PROC_PATHNAME_FREEBSD 12
|
||||
#define KERN_PROC_PATHNAME_NETBSD 5
|
||||
|
||||
/**
|
||||
* Absolute path of executable.
|
||||
*
|
||||
* This variable is initialized automatically at startup. The path is
|
||||
* basically `argv[0]` except some extra vetting is done to provide
|
||||
* stronger assurance that the path can be counted upon to exist.
|
||||
*
|
||||
* For example, if your program is executed as a relative path and then
|
||||
* your program calls `chdir()`, then `argv[0]` will be incorrect; but
|
||||
* `program_executable_name` will work, because it prefixed `getcwd()`
|
||||
* early in the initialization phase.
|
||||
*
|
||||
* @see GetInterpreterExecutableName()
|
||||
* @see program_invocation_short_name
|
||||
* @see program_invocation_name
|
||||
*/
|
||||
char program_executable_name[SIZE];
|
||||
|
||||
static textwindows bool GetNtExePath(char executable[SIZE]) {
|
||||
|
@ -88,13 +73,15 @@ static textwindows bool GetNtExePath(char executable[SIZE]) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static textstartup void GetProgramExecutableName(char executable[SIZE],
|
||||
char *argv0, intptr_t *auxv) {
|
||||
static void ReadProgramExecutableName(char executable[SIZE], char *argv0,
|
||||
uintptr_t *auxv) {
|
||||
size_t m;
|
||||
ssize_t n;
|
||||
int cmd[4];
|
||||
char *p, *t;
|
||||
if (IsWindows() && GetNtExePath(executable)) return;
|
||||
if (IsWindows() && GetNtExePath(executable)) {
|
||||
return;
|
||||
}
|
||||
for (p = 0; *auxv; auxv += 2) {
|
||||
if (*auxv == AT_EXECFN) {
|
||||
p = (char *)auxv[1];
|
||||
|
@ -119,19 +106,37 @@ static textstartup void GetProgramExecutableName(char executable[SIZE],
|
|||
executable[n] = 0;
|
||||
}
|
||||
|
||||
textstartup void program_executable_name_init(int argc, char **argv,
|
||||
char **envp, intptr_t *auxv) {
|
||||
/**
|
||||
* Returns absolute path of executable.
|
||||
*
|
||||
* This variable is initialized automatically at startup. The path is
|
||||
* basically `argv[0]` except some extra vetting is done to provide
|
||||
* stronger assurance that the path can be counted upon to exist.
|
||||
*
|
||||
* For example, if your program is executed as a relative path and then
|
||||
* your program calls `chdir()`, then `argv[0]` will be incorrect; but
|
||||
* `program_executable_name` will work, because it prefixed `getcwd()`
|
||||
* early in the initialization phase.
|
||||
*
|
||||
* @see GetInterpreterExecutableName()
|
||||
* @see program_invocation_short_name
|
||||
* @see program_invocation_name
|
||||
*/
|
||||
char *GetProgramExecutableName(void) {
|
||||
int e;
|
||||
static bool once;
|
||||
char executable[SIZE];
|
||||
if (!cmpxchg(&once, 0, 1)) return;
|
||||
e = errno;
|
||||
GetProgramExecutableName(executable, argv[0], auxv);
|
||||
errno = e;
|
||||
__stpcpy(program_executable_name, executable);
|
||||
STRACE("program_executable_name → %#s", program_executable_name);
|
||||
if (!once) {
|
||||
e = errno;
|
||||
ReadProgramExecutableName(executable, __argv[0], __auxv);
|
||||
errno = e;
|
||||
__stpcpy(program_executable_name, executable);
|
||||
once = true;
|
||||
}
|
||||
return program_executable_name;
|
||||
}
|
||||
|
||||
// try our best to memoize it before a chdir() happens
|
||||
const void *const program_executable_name_init_ctor[] initarray = {
|
||||
program_executable_name_init,
|
||||
GetProgramExecutableName,
|
||||
};
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/struct/iovec.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
|
@ -39,22 +40,26 @@
|
|||
* @asyncsignalsafe
|
||||
*/
|
||||
ssize_t read(int fd, void *buf, size_t size) {
|
||||
ssize_t rc;
|
||||
if (fd >= 0) {
|
||||
if (IsAsan() && !__asan_is_valid(buf, size)) return efault();
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
return weaken(__zipos_read)(
|
||||
if (IsAsan() && !__asan_is_valid(buf, size)) {
|
||||
rc = efault();
|
||||
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
rc = weaken(__zipos_read)(
|
||||
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle,
|
||||
&(struct iovec){buf, size}, 1, -1);
|
||||
} else if (!IsWindows() && !IsMetal()) {
|
||||
return sys_read(fd, buf, size);
|
||||
rc = sys_read(fd, buf, size);
|
||||
} else if (fd >= g_fds.n) {
|
||||
return ebadf();
|
||||
rc = ebadf();
|
||||
} else if (IsMetal()) {
|
||||
return sys_readv_metal(g_fds.p + fd, &(struct iovec){buf, size}, 1);
|
||||
rc = sys_readv_metal(g_fds.p + fd, &(struct iovec){buf, size}, 1);
|
||||
} else {
|
||||
return sys_readv_nt(g_fds.p + fd, &(struct iovec){buf, size}, 1);
|
||||
rc = sys_readv_nt(g_fds.p + fd, &(struct iovec){buf, size}, 1);
|
||||
}
|
||||
} else {
|
||||
return einval();
|
||||
rc = einval();
|
||||
}
|
||||
STRACE("read(%d, %p, %'zu) → %'zd% m", fd, buf, size, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/struct/iovec.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sock/internal.h"
|
||||
|
@ -32,21 +33,25 @@
|
|||
* @asyncsignalsafe
|
||||
*/
|
||||
ssize_t readv(int fd, const struct iovec *iov, int iovlen) {
|
||||
ssize_t rc;
|
||||
if (fd >= 0 && iovlen >= 0) {
|
||||
if (IsAsan() && !__asan_is_valid_iov(iov, iovlen)) return efault();
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
return weaken(__zipos_read)(
|
||||
if (IsAsan() && !__asan_is_valid_iov(iov, iovlen)) {
|
||||
rc = efault();
|
||||
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
rc = weaken(__zipos_read)(
|
||||
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, iov, iovlen, -1);
|
||||
} else if (!IsWindows() && !IsMetal()) {
|
||||
return sys_readv(fd, iov, iovlen);
|
||||
rc = sys_readv(fd, iov, iovlen);
|
||||
} else if (fd >= g_fds.n) {
|
||||
return ebadf();
|
||||
rc = ebadf();
|
||||
} else if (IsMetal()) {
|
||||
return sys_readv_metal(g_fds.p + fd, iov, iovlen);
|
||||
rc = sys_readv_metal(g_fds.p + fd, iov, iovlen);
|
||||
} else {
|
||||
return sys_readv_nt(g_fds.p + fd, iov, iovlen);
|
||||
rc = sys_readv_nt(g_fds.p + fd, iov, iovlen);
|
||||
}
|
||||
} else {
|
||||
return einval();
|
||||
rc = einval();
|
||||
}
|
||||
STRACE("readv(%d, %p, %d) → %'zd% m", fd, iov, iovlen, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/calls/struct/iovec.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
|
@ -37,22 +38,26 @@
|
|||
* @asyncsignalsafe
|
||||
*/
|
||||
ssize_t write(int fd, const void *buf, size_t size) {
|
||||
ssize_t rc;
|
||||
if (fd >= 0) {
|
||||
if (IsAsan() && !__asan_is_valid(buf, size)) return efault();
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
return weaken(__zipos_write)(
|
||||
if (IsAsan() && !__asan_is_valid(buf, size)) {
|
||||
rc = efault();
|
||||
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
rc = weaken(__zipos_write)(
|
||||
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle,
|
||||
&(struct iovec){buf, size}, 1, -1);
|
||||
} else if (!IsWindows() && !IsMetal()) {
|
||||
return sys_write(fd, buf, size);
|
||||
rc = sys_write(fd, buf, size);
|
||||
} else if (fd >= g_fds.n) {
|
||||
return ebadf();
|
||||
rc = ebadf();
|
||||
} else if (IsMetal()) {
|
||||
return sys_writev_metal(g_fds.p + fd, &(struct iovec){buf, size}, 1);
|
||||
rc = sys_writev_metal(g_fds.p + fd, &(struct iovec){buf, size}, 1);
|
||||
} else {
|
||||
return sys_writev_nt(fd, &(struct iovec){buf, size}, 1);
|
||||
rc = sys_writev_nt(fd, &(struct iovec){buf, size}, 1);
|
||||
}
|
||||
} else {
|
||||
return einval();
|
||||
rc = einval();
|
||||
}
|
||||
STRACE("write(%d, %p, %'zu) → %'zd% m", fd, buf, size, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "libc/bits/weaken.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/internal.h"
|
||||
#include "libc/calls/strace.internal.h"
|
||||
#include "libc/intrin/asan.internal.h"
|
||||
#include "libc/sock/internal.h"
|
||||
#include "libc/sysv/errfuns.h"
|
||||
|
@ -35,21 +36,25 @@
|
|||
* @return number of bytes actually handed off, or -1 w/ errno
|
||||
*/
|
||||
ssize_t writev(int fd, const struct iovec *iov, int iovlen) {
|
||||
ssize_t rc;
|
||||
if (fd >= 0 && iovlen >= 0) {
|
||||
if (IsAsan() && !__asan_is_valid_iov(iov, iovlen)) return efault();
|
||||
if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
return weaken(__zipos_write)(
|
||||
if (IsAsan() && !__asan_is_valid_iov(iov, iovlen)) {
|
||||
rc = efault();
|
||||
} else if (fd < g_fds.n && g_fds.p[fd].kind == kFdZip) {
|
||||
rc = weaken(__zipos_write)(
|
||||
(struct ZiposHandle *)(intptr_t)g_fds.p[fd].handle, iov, iovlen, -1);
|
||||
} else if (!IsWindows() && !IsMetal()) {
|
||||
return sys_writev(fd, iov, iovlen);
|
||||
rc = sys_writev(fd, iov, iovlen);
|
||||
} else if (fd >= g_fds.n) {
|
||||
return ebadf();
|
||||
rc = ebadf();
|
||||
} else if (IsMetal()) {
|
||||
return sys_writev_metal(g_fds.p + fd, iov, iovlen);
|
||||
rc = sys_writev_metal(g_fds.p + fd, iov, iovlen);
|
||||
} else {
|
||||
return sys_writev_nt(fd, iov, iovlen);
|
||||
rc = sys_writev_nt(fd, iov, iovlen);
|
||||
}
|
||||
} else {
|
||||
return einval();
|
||||
rc = einval();
|
||||
}
|
||||
STRACE("writev(%d, %p, %d) → %'zd% m", fd, iov, iovlen, rc);
|
||||
return rc;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue