| OLD | NEW |
| 1 #define _GNU_SOURCE | 1 #define _GNU_SOURCE |
| 2 #include <stdio.h> | 2 #include <stdio.h> |
| 3 #include <stdlib.h> | 3 #include <stdlib.h> |
| 4 #include <stdarg.h> | 4 #include <stdarg.h> |
| 5 #include <stddef.h> | 5 #include <stddef.h> |
| 6 #include <string.h> | 6 #include <string.h> |
| 7 #include <unistd.h> | 7 #include <unistd.h> |
| 8 #include <stdint.h> | 8 #include <stdint.h> |
| 9 #include <elf.h> | 9 #include <elf.h> |
| 10 #include <sys/mman.h> | 10 #include <sys/mman.h> |
| 11 #include <limits.h> | 11 #include <limits.h> |
| 12 #include <fcntl.h> | 12 #include <fcntl.h> |
| 13 #include <sys/stat.h> | 13 #include <sys/stat.h> |
| 14 #include <errno.h> | 14 #include <errno.h> |
| 15 #include <link.h> | 15 #include <link.h> |
| 16 #include <setjmp.h> | 16 #include <setjmp.h> |
| 17 #include <pthread.h> | 17 #include <pthread.h> |
| 18 #include <ctype.h> | 18 #include <ctype.h> |
| 19 #include <dlfcn.h> | 19 #include <dlfcn.h> |
| 20 #include "pthread_impl.h" | 20 #include "pthread_impl.h" |
| 21 #include "libc.h" | 21 #include "libc.h" |
| 22 #include "dynlink.h" | 22 #include "dynlink.h" |
| 23 | 23 |
| 24 static void error(const char *, ...); | 24 static void error(const char *, ...); |
| 25 | 25 |
| 26 #ifdef SHARED | |
| 27 | |
| 28 #define MAXP2(a,b) (-(-(a)&-(b))) | 26 #define MAXP2(a,b) (-(-(a)&-(b))) |
| 29 #define ALIGN(x,y) ((x)+(y)-1 & -(y)) | 27 #define ALIGN(x,y) ((x)+(y)-1 & -(y)) |
| 30 | 28 |
| 31 struct debug { | 29 struct debug { |
| 32 int ver; | 30 int ver; |
| 33 void *head; | 31 void *head; |
| 34 void (*bp)(void); | 32 void (*bp)(void); |
| 35 int state; | 33 int state; |
| 36 void *base; | 34 void *base; |
| 37 }; | 35 }; |
| (...skipping 1091 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1129 if (p==&ldso) { | 1127 if (p==&ldso) { |
| 1130 got += i; | 1128 got += i; |
| 1131 } else { | 1129 } else { |
| 1132 while (i--) *got++ += (size_t)base; | 1130 while (i--) *got++ += (size_t)base; |
| 1133 } | 1131 } |
| 1134 j=0; search_vec(p->dynv, &j, DT_MIPS_GOTSYM); | 1132 j=0; search_vec(p->dynv, &j, DT_MIPS_GOTSYM); |
| 1135 i=0; search_vec(p->dynv, &i, DT_MIPS_SYMTABNO); | 1133 i=0; search_vec(p->dynv, &i, DT_MIPS_SYMTABNO); |
| 1136 Sym *sym = p->syms + j; | 1134 Sym *sym = p->syms + j; |
| 1137 rel[0] = (unsigned char *)got - base; | 1135 rel[0] = (unsigned char *)got - base; |
| 1138 for (i-=j; i; i--, sym++, rel[0]+=sizeof(size_t)) { | 1136 for (i-=j; i; i--, sym++, rel[0]+=sizeof(size_t)) { |
| 1139 » » rel[1] = sym-p->syms << 8 | R_MIPS_JUMP_SLOT; | 1137 » » rel[1] = (sym-p->syms) << 8 | R_MIPS_JUMP_SLOT; |
| 1140 do_relocs(p, rel, sizeof rel, 2); | 1138 do_relocs(p, rel, sizeof rel, 2); |
| 1141 } | 1139 } |
| 1142 } | 1140 } |
| 1143 | 1141 |
| 1144 static void reloc_all(struct dso *p) | 1142 static void reloc_all(struct dso *p) |
| 1145 { | 1143 { |
| 1146 size_t dyn[DYN_CNT]; | 1144 size_t dyn[DYN_CNT]; |
| 1147 for (; p; p=p->next) { | 1145 for (; p; p=p->next) { |
| 1148 if (p->relocated) continue; | 1146 if (p->relocated) continue; |
| 1149 decode_vec(p->dynv, dyn, DYN_CNT); | 1147 decode_vec(p->dynv, dyn, DYN_CNT); |
| (...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1327 * replaced later due to copy relocations in the main program. */ | 1325 * replaced later due to copy relocations in the main program. */ |
| 1328 | 1326 |
| 1329 __attribute__((__visibility__("hidden"))) | 1327 __attribute__((__visibility__("hidden"))) |
| 1330 void __dls2(unsigned char *base, size_t *sp) | 1328 void __dls2(unsigned char *base, size_t *sp) |
| 1331 { | 1329 { |
| 1332 if (DL_FDPIC) { | 1330 if (DL_FDPIC) { |
| 1333 void *p1 = (void *)sp[-2]; | 1331 void *p1 = (void *)sp[-2]; |
| 1334 void *p2 = (void *)sp[-1]; | 1332 void *p2 = (void *)sp[-1]; |
| 1335 if (!p1) { | 1333 if (!p1) { |
| 1336 size_t *auxv, aux[AUX_CNT]; | 1334 size_t *auxv, aux[AUX_CNT]; |
| 1337 » » » for (auxv=sp+1+*sp+1; *auxv; auxv++); auxv++; | 1335 » » » for (auxv=sp+1+*sp+1; *auxv; auxv++) |
| 1336 » » » » ; // Pass |
| 1337 » » » auxv++; |
| 1338 decode_vec(auxv, aux, AUX_CNT); | 1338 decode_vec(auxv, aux, AUX_CNT); |
| 1339 if (aux[AT_BASE]) ldso.base = (void *)aux[AT_BASE]; | 1339 if (aux[AT_BASE]) ldso.base = (void *)aux[AT_BASE]; |
| 1340 else ldso.base = (void *)(aux[AT_PHDR] & -4096); | 1340 else ldso.base = (void *)(aux[AT_PHDR] & -4096); |
| 1341 } | 1341 } |
| 1342 app_loadmap = p2 ? p1 : 0; | 1342 app_loadmap = p2 ? p1 : 0; |
| 1343 ldso.loadmap = p2 ? p2 : p1; | 1343 ldso.loadmap = p2 ? p2 : p1; |
| 1344 ldso.base = laddr(&ldso, 0); | 1344 ldso.base = laddr(&ldso, 0); |
| 1345 } else { | 1345 } else { |
| 1346 ldso.base = base; | 1346 ldso.base = base; |
| 1347 } | 1347 } |
| (...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1514 * linker had ldd not taken its place. */ | 1514 * linker had ldd not taken its place. */ |
| 1515 if (ldd_mode) { | 1515 if (ldd_mode) { |
| 1516 for (i=0; i<app.phnum; i++) { | 1516 for (i=0; i<app.phnum; i++) { |
| 1517 if (app.phdr[i].p_type == PT_INTERP) | 1517 if (app.phdr[i].p_type == PT_INTERP) |
| 1518 ldso.name = laddr(&app, app.phdr[i].p_va
ddr); | 1518 ldso.name = laddr(&app, app.phdr[i].p_va
ddr); |
| 1519 } | 1519 } |
| 1520 dprintf(1, "\t%s (%p)\n", ldso.name, ldso.base); | 1520 dprintf(1, "\t%s (%p)\n", ldso.name, ldso.base); |
| 1521 } | 1521 } |
| 1522 } | 1522 } |
| 1523 if (app.tls.size) { | 1523 if (app.tls.size) { |
| 1524 » » libc.tls_head = &app.tls; | 1524 » » libc.tls_head = tls_tail = &app.tls; |
| 1525 app.tls_id = tls_cnt = 1; | 1525 app.tls_id = tls_cnt = 1; |
| 1526 #ifdef TLS_ABOVE_TP | 1526 #ifdef TLS_ABOVE_TP |
| 1527 app.tls.offset = 0; | 1527 app.tls.offset = 0; |
| 1528 tls_offset = app.tls.size | 1528 tls_offset = app.tls.size |
| 1529 + ( -((uintptr_t)app.tls.image + app.tls.size) | 1529 + ( -((uintptr_t)app.tls.image + app.tls.size) |
| 1530 & (app.tls.align-1) ); | 1530 & (app.tls.align-1) ); |
| 1531 #else | 1531 #else |
| 1532 tls_offset = app.tls.offset = app.tls.size | 1532 tls_offset = app.tls.offset = app.tls.size |
| 1533 + ( -((uintptr_t)app.tls.image + app.tls.size) | 1533 + ( -((uintptr_t)app.tls.image + app.tls.size) |
| 1534 & (app.tls.align-1) ); | 1534 & (app.tls.align-1) ); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1577 /* Donate unused parts of app and library mapping to malloc */ | 1577 /* Donate unused parts of app and library mapping to malloc */ |
| 1578 reclaim_gaps(&app); | 1578 reclaim_gaps(&app); |
| 1579 reclaim_gaps(&ldso); | 1579 reclaim_gaps(&ldso); |
| 1580 | 1580 |
| 1581 /* Load preload/needed libraries, add their symbols to the global | 1581 /* Load preload/needed libraries, add their symbols to the global |
| 1582 * namespace, and perform all remaining relocations. */ | 1582 * namespace, and perform all remaining relocations. */ |
| 1583 if (env_preload) load_preload(env_preload); | 1583 if (env_preload) load_preload(env_preload); |
| 1584 load_deps(&app); | 1584 load_deps(&app); |
| 1585 make_global(&app); | 1585 make_global(&app); |
| 1586 | 1586 |
| 1587 #ifndef DYNAMIC_IS_RO | 1587 » for (i=0; app.dynv[i]; i+=2) { |
| 1588 » for (i=0; app.dynv[i]; i+=2) | 1588 » » if (!DT_DEBUG_INDIRECT && app.dynv[i]==DT_DEBUG) |
| 1589 » » if (app.dynv[i]==DT_DEBUG) | |
| 1590 app.dynv[i+1] = (size_t)&debug; | 1589 app.dynv[i+1] = (size_t)&debug; |
| 1591 #endif | 1590 » » if (DT_DEBUG_INDIRECT && app.dynv[i]==DT_DEBUG_INDIRECT) { |
| 1591 » » » size_t *ptr = (size_t *) app.dynv[i+1]; |
| 1592 » » » *ptr = (size_t)&debug; |
| 1593 » » } |
| 1594 » } |
| 1592 | 1595 |
| 1593 /* The main program must be relocated LAST since it may contin | 1596 /* The main program must be relocated LAST since it may contin |
| 1594 * copy relocations which depend on libraries' relocations. */ | 1597 * copy relocations which depend on libraries' relocations. */ |
| 1595 reloc_all(app.next); | 1598 reloc_all(app.next); |
| 1596 reloc_all(&app); | 1599 reloc_all(&app); |
| 1597 | 1600 |
| 1598 update_tls_size(); | 1601 update_tls_size(); |
| 1599 if (libc.tls_size > sizeof builtin_tls || tls_align > MIN_TLS_ALIGN) { | 1602 if (libc.tls_size > sizeof builtin_tls || tls_align > MIN_TLS_ALIGN) { |
| 1600 void *initial_tls = calloc(libc.tls_size, 1); | 1603 void *initial_tls = calloc(libc.tls_size, 1); |
| 1601 if (!initial_tls) { | 1604 if (!initial_tls) { |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1726 orig_tail = tail; | 1729 orig_tail = tail; |
| 1727 end: | 1730 end: |
| 1728 __release_ptc(); | 1731 __release_ptc(); |
| 1729 if (p) gencnt++; | 1732 if (p) gencnt++; |
| 1730 pthread_rwlock_unlock(&lock); | 1733 pthread_rwlock_unlock(&lock); |
| 1731 if (p) do_init_fini(orig_tail); | 1734 if (p) do_init_fini(orig_tail); |
| 1732 pthread_setcancelstate(cs, 0); | 1735 pthread_setcancelstate(cs, 0); |
| 1733 return p; | 1736 return p; |
| 1734 } | 1737 } |
| 1735 | 1738 |
| 1736 static int invalid_dso_handle(void *h) | 1739 __attribute__((__visibility__("hidden"))) |
| 1740 int __dl_invalid_handle(void *h) |
| 1737 { | 1741 { |
| 1738 struct dso *p; | 1742 struct dso *p; |
| 1739 for (p=head; p; p=p->next) if (h==p) return 0; | 1743 for (p=head; p; p=p->next) if (h==p) return 0; |
| 1740 error("Invalid library handle %p", (void *)h); | 1744 error("Invalid library handle %p", (void *)h); |
| 1741 return 1; | 1745 return 1; |
| 1742 } | 1746 } |
| 1743 | 1747 |
| 1744 static void *addr2dso(size_t a) | 1748 static void *addr2dso(size_t a) |
| 1745 { | 1749 { |
| 1746 struct dso *p; | 1750 struct dso *p; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1781 p = p->next; | 1785 p = p->next; |
| 1782 } | 1786 } |
| 1783 struct symdef def = find_sym(p, s, 0); | 1787 struct symdef def = find_sym(p, s, 0); |
| 1784 if (!def.sym) goto failed; | 1788 if (!def.sym) goto failed; |
| 1785 if ((def.sym->st_info&0xf) == STT_TLS) | 1789 if ((def.sym->st_info&0xf) == STT_TLS) |
| 1786 return __tls_get_addr((size_t []){def.dso->tls_id, def.s
ym->st_value}); | 1790 return __tls_get_addr((size_t []){def.dso->tls_id, def.s
ym->st_value}); |
| 1787 if (DL_FDPIC && (def.sym->st_info&0xf) == STT_FUNC) | 1791 if (DL_FDPIC && (def.sym->st_info&0xf) == STT_FUNC) |
| 1788 return def.dso->funcdescs + (def.sym - def.dso->syms); | 1792 return def.dso->funcdescs + (def.sym - def.dso->syms); |
| 1789 return laddr(def.dso, def.sym->st_value); | 1793 return laddr(def.dso, def.sym->st_value); |
| 1790 } | 1794 } |
| 1791 » if (invalid_dso_handle(p)) | 1795 » if (__dl_invalid_handle(p)) |
| 1792 return 0; | 1796 return 0; |
| 1793 if ((ght = p->ghashtab)) { | 1797 if ((ght = p->ghashtab)) { |
| 1794 gh = gnu_hash(s); | 1798 gh = gnu_hash(s); |
| 1795 sym = gnu_lookup(gh, ght, p, s); | 1799 sym = gnu_lookup(gh, ght, p, s); |
| 1796 } else { | 1800 } else { |
| 1797 h = sysv_hash(s); | 1801 h = sysv_hash(s); |
| 1798 sym = sysv_lookup(s, h, p); | 1802 sym = sysv_lookup(s, h, p); |
| 1799 } | 1803 } |
| 1800 if (sym && (sym->st_info&0xf) == STT_TLS) | 1804 if (sym && (sym->st_info&0xf) == STT_TLS) |
| 1801 return __tls_get_addr((size_t []){p->tls_id, sym->st_value}); | 1805 return __tls_get_addr((size_t []){p->tls_id, sym->st_value}); |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1816 if (DL_FDPIC && sym && sym->st_shndx && (sym->st_info&0xf) == ST
T_FUNC) | 1820 if (DL_FDPIC && sym && sym->st_shndx && (sym->st_info&0xf) == ST
T_FUNC) |
| 1817 return p->deps[i]->funcdescs + (sym - p->deps[i]->syms); | 1821 return p->deps[i]->funcdescs + (sym - p->deps[i]->syms); |
| 1818 if (sym && sym->st_value && (1<<(sym->st_info&0xf) & OK_TYPES)) | 1822 if (sym && sym->st_value && (1<<(sym->st_info&0xf) & OK_TYPES)) |
| 1819 return laddr(p->deps[i], sym->st_value); | 1823 return laddr(p->deps[i], sym->st_value); |
| 1820 } | 1824 } |
| 1821 failed: | 1825 failed: |
| 1822 error("Symbol not found: %s", s); | 1826 error("Symbol not found: %s", s); |
| 1823 return 0; | 1827 return 0; |
| 1824 } | 1828 } |
| 1825 | 1829 |
| 1826 int __dladdr(const void *addr, Dl_info *info) | 1830 int dladdr(const void *addr, Dl_info *info) |
| 1827 { | 1831 { |
| 1828 struct dso *p; | 1832 struct dso *p; |
| 1829 Sym *sym, *bestsym; | 1833 Sym *sym, *bestsym; |
| 1830 uint32_t nsym; | 1834 uint32_t nsym; |
| 1831 char *strings; | 1835 char *strings; |
| 1832 void *best = 0; | 1836 void *best = 0; |
| 1833 | 1837 |
| 1834 pthread_rwlock_rdlock(&lock); | 1838 pthread_rwlock_rdlock(&lock); |
| 1835 p = addr2dso((size_t)addr); | 1839 p = addr2dso((size_t)addr); |
| 1836 pthread_rwlock_unlock(&lock); | 1840 pthread_rwlock_unlock(&lock); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1905 ret = (callback)(&info, sizeof (info), data); | 1909 ret = (callback)(&info, sizeof (info), data); |
| 1906 | 1910 |
| 1907 if (ret != 0) break; | 1911 if (ret != 0) break; |
| 1908 | 1912 |
| 1909 pthread_rwlock_rdlock(&lock); | 1913 pthread_rwlock_rdlock(&lock); |
| 1910 current = current->next; | 1914 current = current->next; |
| 1911 pthread_rwlock_unlock(&lock); | 1915 pthread_rwlock_unlock(&lock); |
| 1912 } | 1916 } |
| 1913 return ret; | 1917 return ret; |
| 1914 } | 1918 } |
| 1915 #else | |
| 1916 static int invalid_dso_handle(void *h) | |
| 1917 { | |
| 1918 error("Invalid library handle %p", (void *)h); | |
| 1919 return 1; | |
| 1920 } | |
| 1921 void *dlopen(const char *file, int mode) | |
| 1922 { | |
| 1923 error("Dynamic loading not supported"); | |
| 1924 return 0; | |
| 1925 } | |
| 1926 void *__dlsym(void *restrict p, const char *restrict s, void *restrict ra) | |
| 1927 { | |
| 1928 error("Symbol not found: %s", s); | |
| 1929 return 0; | |
| 1930 } | |
| 1931 int __dladdr (const void *addr, Dl_info *info) | |
| 1932 { | |
| 1933 return 0; | |
| 1934 } | |
| 1935 #endif | |
| 1936 | 1919 |
| 1937 int __dlinfo(void *dso, int req, void *res) | 1920 __attribute__((__visibility__("hidden"))) |
| 1938 { | 1921 void __dl_vseterr(const char *, va_list); |
| 1939 » if (invalid_dso_handle(dso)) return -1; | |
| 1940 » if (req != RTLD_DI_LINKMAP) { | |
| 1941 » » error("Unsupported request %d", req); | |
| 1942 » » return -1; | |
| 1943 » } | |
| 1944 » *(struct link_map **)res = dso; | |
| 1945 » return 0; | |
| 1946 } | |
| 1947 | |
| 1948 char *dlerror() | |
| 1949 { | |
| 1950 » pthread_t self = __pthread_self(); | |
| 1951 » if (!self->dlerror_flag) return 0; | |
| 1952 » self->dlerror_flag = 0; | |
| 1953 » char *s = self->dlerror_buf; | |
| 1954 » if (s == (void *)-1) | |
| 1955 » » return "Dynamic linker failed to allocate memory for error messa
ge"; | |
| 1956 » else | |
| 1957 » » return s; | |
| 1958 } | |
| 1959 | |
| 1960 int dlclose(void *p) | |
| 1961 { | |
| 1962 » return invalid_dso_handle(p); | |
| 1963 } | |
| 1964 | |
| 1965 void __dl_thread_cleanup(void) | |
| 1966 { | |
| 1967 » pthread_t self = __pthread_self(); | |
| 1968 » if (self->dlerror_buf != (void *)-1) | |
| 1969 » » free(self->dlerror_buf); | |
| 1970 } | |
| 1971 | 1922 |
| 1972 static void error(const char *fmt, ...) | 1923 static void error(const char *fmt, ...) |
| 1973 { | 1924 { |
| 1974 va_list ap; | 1925 va_list ap; |
| 1975 va_start(ap, fmt); | 1926 va_start(ap, fmt); |
| 1976 #ifdef SHARED | |
| 1977 if (!runtime) { | 1927 if (!runtime) { |
| 1978 vdprintf(2, fmt, ap); | 1928 vdprintf(2, fmt, ap); |
| 1979 dprintf(2, "\n"); | 1929 dprintf(2, "\n"); |
| 1980 ldso_fail = 1; | 1930 ldso_fail = 1; |
| 1981 va_end(ap); | 1931 va_end(ap); |
| 1982 return; | 1932 return; |
| 1983 } | 1933 } |
| 1984 #endif | 1934 » __dl_vseterr(fmt, ap); |
| 1985 » pthread_t self = __pthread_self(); | |
| 1986 » if (self->dlerror_buf != (void *)-1) | |
| 1987 » » free(self->dlerror_buf); | |
| 1988 » size_t len = vsnprintf(0, 0, fmt, ap); | |
| 1989 va_end(ap); | 1935 va_end(ap); |
| 1990 char *buf = malloc(len+1); | |
| 1991 if (buf) { | |
| 1992 va_start(ap, fmt); | |
| 1993 vsnprintf(buf, len+1, fmt, ap); | |
| 1994 va_end(ap); | |
| 1995 } else { | |
| 1996 buf = (void *)-1; | |
| 1997 } | |
| 1998 self->dlerror_buf = buf; | |
| 1999 self->dlerror_flag = 1; | |
| 2000 } | 1936 } |
| OLD | NEW |