b3559471f36cd222c3dde3feb110211d8962d3ab
[librecmc/librecmc.git] / toolchain / musl / patches / 020-mips-dlsym_donot_return_address_from_undef_sym.patch
1 >From a57cd35acf26ba6202ed6534a57f496464f431a1 Mon Sep 17 00:00:00 2001
2 From: Szabolcs Nagy <nsz@port70.net>
3 Date: Sat, 10 Aug 2019 23:14:40 +0000
4 Subject: [PATCH] make relocation time symbol lookup and dlsym consistent
5
6 Using common code path for all symbol lookups fixes three dlsym issues:
7
8 - st_shndx of STT_TLS symbols were not checked and thus an undefined
9   tls symbol reference could be incorrectly treated as a definition
10   (the sysv hash lookup returns undefined symbols, gnu does not, so should
11   be rare in practice).
12
13 - symbol binding was not checked so a hidden symbol may be returned
14   (in principle STB_LOCAL symbols may appear in the dynamic symbol table
15   for hidden symbols, but linkers most likely don't produce it).
16
17 - mips specific behaviour was not applied (ARCH_SYM_REJECT_UND) so
18   undefined symbols may be returned on mips.
19
20 always_inline is used to avoid relocation performance regression, the
21 code generation for find_sym should not be affected.
22 ---
23  ldso/dynlink.c | 84 +++++++++++++++++++-------------------------------
24  1 file changed, 31 insertions(+), 53 deletions(-)
25
26 --- a/ldso/dynlink.c
27 +++ b/ldso/dynlink.c
28 @@ -283,12 +283,16 @@ static Sym *gnu_lookup_filtered(uint32_t
29  #define ARCH_SYM_REJECT_UND(s) 0
30  #endif
31  
32 -static struct symdef find_sym(struct dso *dso, const char *s, int need_def)
33 +#if defined(__GNUC__)
34 +__attribute__((always_inline))
35 +#endif
36 +static inline struct symdef find_sym2(struct dso *dso, const char *s, int need_def, int use_deps)
37  {
38         uint32_t h = 0, gh = gnu_hash(s), gho = gh / (8*sizeof(size_t)), *ght;
39         size_t ghm = 1ul << gh % (8*sizeof(size_t));
40         struct symdef def = {0};
41 -       for (; dso; dso=dso->syms_next) {
42 +       struct dso **deps = use_deps ? dso->deps : 0;
43 +       for (; dso; dso=use_deps ? *deps++ : dso->syms_next) {
44                 Sym *sym;
45                 if ((ght = dso->ghashtab)) {
46                         sym = gnu_lookup_filtered(gh, ght, dso, s, gho, ghm);
47 @@ -313,6 +317,11 @@ static struct symdef find_sym(struct dso
48         return def;
49  }
50  
51 +static struct symdef find_sym(struct dso *dso, const char *s, int need_def)
52 +{
53 +       return find_sym2(dso, s, need_def, 0);
54 +}
55 +
56  static void do_relocs(struct dso *dso, size_t *rel, size_t rel_size, size_t stride)
57  {
58         unsigned char *base = dso->base;
59 @@ -2118,58 +2127,27 @@ static void *addr2dso(size_t a)
60  
61  static void *do_dlsym(struct dso *p, const char *s, void *ra)
62  {
63 -       size_t i;
64 -       uint32_t h = 0, gh = 0, *ght;
65 -       Sym *sym;
66 -       if (p == head || p == RTLD_DEFAULT || p == RTLD_NEXT) {
67 -               if (p == RTLD_DEFAULT) {
68 -                       p = head;
69 -               } else if (p == RTLD_NEXT) {
70 -                       p = addr2dso((size_t)ra);
71 -                       if (!p) p=head;
72 -                       p = p->next;
73 -               }
74 -               struct symdef def = find_sym(p, s, 0);
75 -               if (!def.sym) goto failed;
76 -               if ((def.sym->st_info&0xf) == STT_TLS)
77 -                       return __tls_get_addr((tls_mod_off_t []){def.dso->tls_id, def.sym->st_value-DTP_OFFSET});
78 -               if (DL_FDPIC && (def.sym->st_info&0xf) == STT_FUNC)
79 -                       return def.dso->funcdescs + (def.sym - def.dso->syms);
80 -               return laddr(def.dso, def.sym->st_value);
81 -       }
82 -       if (__dl_invalid_handle(p))
83 +       int use_deps = 0;
84 +       if (p == head || p == RTLD_DEFAULT) {
85 +               p = head;
86 +       } else if (p == RTLD_NEXT) {
87 +               p = addr2dso((size_t)ra);
88 +               if (!p) p=head;
89 +               p = p->next;
90 +       } else if (__dl_invalid_handle(p)) {
91 +               return 0;
92 +       } else
93 +               use_deps = 1;
94 +       struct symdef def = find_sym2(p, s, 0, use_deps);
95 +       if (!def.sym) {
96 +               error("Symbol not found: %s", s);
97                 return 0;
98 -       if ((ght = p->ghashtab)) {
99 -               gh = gnu_hash(s);
100 -               sym = gnu_lookup(gh, ght, p, s);
101 -       } else {
102 -               h = sysv_hash(s);
103 -               sym = sysv_lookup(s, h, p);
104 -       }
105 -       if (sym && (sym->st_info&0xf) == STT_TLS)
106 -               return __tls_get_addr((tls_mod_off_t []){p->tls_id, sym->st_value-DTP_OFFSET});
107 -       if (DL_FDPIC && sym && sym->st_shndx && (sym->st_info&0xf) == STT_FUNC)
108 -               return p->funcdescs + (sym - p->syms);
109 -       if (sym && sym->st_value && (1<<(sym->st_info&0xf) & OK_TYPES))
110 -               return laddr(p, sym->st_value);
111 -       for (i=0; p->deps[i]; i++) {
112 -               if ((ght = p->deps[i]->ghashtab)) {
113 -                       if (!gh) gh = gnu_hash(s);
114 -                       sym = gnu_lookup(gh, ght, p->deps[i], s);
115 -               } else {
116 -                       if (!h) h = sysv_hash(s);
117 -                       sym = sysv_lookup(s, h, p->deps[i]);
118 -               }
119 -               if (sym && (sym->st_info&0xf) == STT_TLS)
120 -                       return __tls_get_addr((tls_mod_off_t []){p->deps[i]->tls_id, sym->st_value-DTP_OFFSET});
121 -               if (DL_FDPIC && sym && sym->st_shndx && (sym->st_info&0xf) == STT_FUNC)
122 -                       return p->deps[i]->funcdescs + (sym - p->deps[i]->syms);
123 -               if (sym && sym->st_value && (1<<(sym->st_info&0xf) & OK_TYPES))
124 -                       return laddr(p->deps[i], sym->st_value);
125         }
126 -failed:
127 -       error("Symbol not found: %s", s);
128 -       return 0;
129 +       if ((def.sym->st_info&0xf) == STT_TLS)
130 +               return __tls_get_addr((tls_mod_off_t []){def.dso->tls_id, def.sym->st_value-DTP_OFFSET});
131 +       if (DL_FDPIC && (def.sym->st_info&0xf) == STT_FUNC)
132 +               return def.dso->funcdescs + (def.sym - def.dso->syms);
133 +       return laddr(def.dso, def.sym->st_value);
134  }
135  
136  int dladdr(const void *addr_arg, Dl_info *info)