diff options
Diffstat (limited to 'ldso/ldso/dl-elf.c')
-rw-r--r-- | ldso/ldso/dl-elf.c | 131 |
1 files changed, 131 insertions, 0 deletions
diff --git a/ldso/ldso/dl-elf.c b/ldso/ldso/dl-elf.c index cef44965e..5a1c89230 100644 --- a/ldso/ldso/dl-elf.c +++ b/ldso/ldso/dl-elf.c @@ -793,3 +793,134 @@ int _dl_fixup(struct dyn_elf *rpnt, int flag) return goof; } +/* Minimal printf which handles only %s, %d, and %x */ +void _dl_dprintf(int fd, const char *fmt, ...) +{ + int num; + va_list args; + char *start, *ptr, *string; + static char *buf; + + buf = _dl_mmap((void *) 0, PAGE_SIZE, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); + if (_dl_mmap_check_error(buf)) { + _dl_write(fd, "mmap of a spare page failed!\n", 29); + _dl_exit(20); + } + + start = ptr = buf; + + if (!fmt) + return; + + if (_dl_strlen(fmt) >= (PAGE_SIZE - 1)) { + _dl_write(fd, "overflow\n", 11); + _dl_exit(20); + } + + _dl_strcpy(buf, fmt); + va_start(args, fmt); + + while (start) { + while (*ptr != '%' && *ptr) { + ptr++; + } + + if (*ptr == '%') { + *ptr++ = '\0'; + _dl_write(fd, start, _dl_strlen(start)); + + switch (*ptr++) { + case 's': + string = va_arg(args, char *); + + if (!string) + _dl_write(fd, "(null)", 6); + else + _dl_write(fd, string, _dl_strlen(string)); + break; + + case 'i': + case 'd': + { + char tmp[22]; + num = va_arg(args, int); + + string = _dl_simple_ltoa(tmp, num); + _dl_write(fd, string, _dl_strlen(string)); + break; + } + case 'x': + case 'X': + { + char tmp[22]; + num = va_arg(args, int); + + string = _dl_simple_ltoahex(tmp, num); + _dl_write(fd, string, _dl_strlen(string)); + break; + } + default: + _dl_write(fd, "(null)", 6); + break; + } + + start = ptr; + } else { + _dl_write(fd, start, _dl_strlen(start)); + start = NULL; + } + } + _dl_munmap(buf, PAGE_SIZE); + return; +} + +char *_dl_strdup(const char *string) +{ + char *retval; + int len; + + len = _dl_strlen(string); + retval = _dl_malloc(len + 1); + _dl_strcpy(retval, string); + return retval; +} + +void *(*_dl_malloc_function) (size_t size) = NULL; +void *_dl_malloc(int size) +{ + void *retval; + +#if 0 +#ifdef __SUPPORT_LD_DEBUG_EARLY__ + _dl_dprintf(2, "malloc: request for %d bytes\n", size); +#endif +#endif + + if (_dl_malloc_function) + return (*_dl_malloc_function) (size); + + if (_dl_malloc_addr - _dl_mmap_zero + size > PAGE_SIZE) { +#ifdef __SUPPORT_LD_DEBUG_EARLY__ + _dl_dprintf(2, "malloc: mmapping more memory\n"); +#endif + _dl_mmap_zero = _dl_malloc_addr = _dl_mmap((void *) 0, size, + PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0); + if (_dl_mmap_check_error(_dl_mmap_zero)) { + _dl_dprintf(2, "%s: mmap of a spare page failed!\n", _dl_progname); + _dl_exit(20); + } + } + retval = _dl_malloc_addr; + _dl_malloc_addr += size; + + /* + * Align memory to 4 byte boundary. Some platforms require this, others + * simply get better performance. + */ + _dl_malloc_addr = (unsigned char *) (((unsigned long) _dl_malloc_addr + 3) & ~(3)); + return retval; +} + + + |