forked from akawashiro/sloader
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathldsodefs.h
1806 lines (1525 loc) · 70.3 KB
/
ldsodefs.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/* Run-time dynamic linker data structures for loaded ELF shared objects.
Copyright (C) 1995-2022 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
The GNU C Library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
#ifndef _LDSODEFS_H
#define _LDSODEFS_H 1
#include <features.h>
#include <stdbool.h>
#define __need_size_t
#define __need_NULL
#include <dlfcn.h>
#include <elf.h>
#include <fpu_control.h>
// #include <link.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <sys/mman.h>
// TODO (akawashiro)
// #include <dl-lookupcfg.h>
// #include <dl-fixup-attribute.h>
// #include <dl-sysdep.h>
// #include <hp-timing.h>
// #include <libc-lock.h>
// #include <list_t.h>
// #include <tls.h>
// TODO (akawashiro)
#define SHARED
#define IS_IN(lib) 0
#define attribute_hidden __attribute__((visibility("hidden")))
#define attribute_relro __attribute__((section(".data.rel.ro")))
#define rtld_hidden_proto(name, attrs...)
#define libc_hidden_proto(name, attrs...)
#define ElfW(type) Elf64_##type
#define ELFW(type) ELF64_##type
#define DT_THISPROCNUM 0
#define DL_FIXUP_VALUE_TYPE struct fdesc
/* For POSIX.1 systems, the pair of st_dev and st_ino constitute
a unique identifier for a file. */
struct r_file_id {
dev_t dev;
ino64_t ino;
};
struct fdesc {
ElfW(Addr) ip; /* code entry point */
ElfW(Addr) gp; /* global pointer */
};
struct link_map_machine {
Elf32_Addr plt; /* Address of .plt + 36 */
Elf32_Addr gotplt; /* Address of .got + 0x0c */
};
typedef uint32_t Elf_Symndx;
/* Forward declaration. */
struct link_map;
/* Structure to describe a single list of scope elements. The lookup
functions get passed an array of pointers to such structures. */
struct r_scope_elem {
/* Array of maps for the scope. */
struct link_map **r_list;
/* Number of entries in the scope. */
unsigned int r_nlist;
};
struct r_debug {
/* Version number for this protocol. It should be greater than 0. */
int r_version;
struct link_map *r_map; /* Head of the chain of loaded objects. */
/* This is the address of a function internal to the run-time linker,
that will always be called when the linker begins to map in a
library or unmap it, and again when the mapping change is complete.
The debugger can set a breakpoint at this address if it wants to
notice shared object mapping changes. */
ElfW(Addr) r_brk;
enum {
/* This state value describes the mapping change taking place when
the `r_brk' address is called. */
RT_CONSISTENT, /* Mapping change is complete. */
RT_ADD, /* Beginning to add a new object. */
RT_DELETE /* Beginning to remove an object mapping. */
} r_state;
ElfW(Addr) r_ldbase; /* Base address the linker is loaded at. */
};
/* This is the symbol of that structure provided by the dynamic linker. */
extern struct r_debug _r_debug;
/* The extended rendezvous structure used by the run-time dynamic linker
to communicate details of shared object loading to the debugger. If
the executable's dynamic section has a DT_DEBUG element, the run-time
linker sets that element's value to the address where this structure
can be found. */
struct r_debug_extended {
struct r_debug base;
/* The following field is added by r_version == 2. */
/* Link to the next r_debug_extended structure. Each r_debug_extended
structure represents a different namespace. The first
r_debug_extended structure is for the default namespace. */
struct r_debug_extended *r_next;
};
/* Structure to record search path and allocation mechanism. */
struct r_search_path_struct {
struct r_search_path_elem **dirs;
int malloced;
};
struct auditstate {
uintptr_t cookie;
unsigned int bindflags;
};
__BEGIN_DECLS
#define VERSYMIDX(sym) (DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGIDX(sym))
#define VALIDX(tag) \
(DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM + DT_EXTRANUM + \
DT_VALTAGIDX(tag))
#define ADDRIDX(tag) \
(DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM + \
DT_ADDRTAGIDX(tag))
/* Type of GNU hash which the machine uses. */
#ifndef ELF_MACHINE_GNU_HASH_ADDRIDX
#define ELF_MACHINE_GNU_HASH_ADDRIDX ADDRIDX(DT_GNU_HASH)
#endif
/* Calculate the index of a symbol in GNU hash. */
#ifndef ELF_MACHINE_HASH_SYMIDX
#define ELF_MACHINE_HASH_SYMIDX(map, hasharr) \
((hasharr) - (map)->l_gnu_chain_zero)
#endif
/* Setup MIPS xhash. Defined only for MIPS. */
#ifndef ELF_MACHINE_XHASH_SETUP
#define ELF_MACHINE_XHASH_SETUP(hash32, symbias, map) \
((void)(hash32), (void)(symbias), (void)(map))
#endif
/* We use this macro to refer to ELF types independent of the native wordsize.
`ElfW(TYPE)' is used in place of `Elf32_TYPE' or `Elf64_TYPE'. */
// #define ELFW(type) _ElfW(ELF, __ELF_NATIVE_CLASS, type)
/* Return true if dynamic section in the shared library L should be
relocated. */
// TODO (akawashiro)
// static inline bool dl_relocate_ld(const struct link_map *l) {
// /* Don't relocate dynamic section if it is readonly */
// return !(l->l_ld_readonly || DL_RO_DYN_SECTION);
// }
/* All references to the value of l_info[DT_PLTGOT],
l_info[DT_STRTAB], l_info[DT_SYMTAB], l_info[DT_RELA],
l_info[DT_REL], l_info[DT_JMPREL], and l_info[VERSYMIDX (DT_VERSYM)]
have to be accessed via the D_PTR macro. The macro is needed since for
most architectures the entry is already relocated - but for some not
and we need to relocate at access time. */
// TODO (akawashiro)
/*
#define D_PTR(map, i) \
((map)->i->d_un.d_ptr + (dl_relocate_ld(map) ? 0 : (map)->l_addr))
*/
/* Result of the lookup functions and how to retrieve the base address. */
typedef struct link_map *lookup_t;
#define LOOKUP_VALUE(map) map
#define LOOKUP_VALUE_ADDRESS(map, set) ((set) || (map) ? (map)->l_addr : 0)
/* Calculate the address of symbol REF using the base address from map MAP,
if non-NULL. Don't check for NULL map if MAP_SET is TRUE. */
#define SYMBOL_ADDRESS(map, ref, map_set) \
((ref) == NULL ? 0 \
: (__glibc_unlikely((ref)->st_shndx == SHN_ABS) \
? 0 \
: LOOKUP_VALUE_ADDRESS(map, map_set)) + \
(ref)->st_value)
/* Type of a constructor function, in DT_INIT, DT_INIT_ARRAY,
DT_PREINIT_ARRAY. */
typedef void (*dl_init_t)(int, char **, char **);
/* On some architectures a pointer to a function is not just a pointer
to the actual code of the function but rather an architecture
specific descriptor. */
#ifndef ELF_FUNCTION_PTR_IS_SPECIAL
#define DL_SYMBOL_ADDRESS(map, ref) (void *)SYMBOL_ADDRESS(map, ref, false)
#define DL_LOOKUP_ADDRESS(addr) ((ElfW(Addr))(addr))
#define DL_CALL_DT_INIT(map, start, argc, argv, env) \
((dl_init_t)(start))(argc, argv, env)
#define DL_CALL_DT_FINI(map, start) ((fini_t)(start))()
#endif
/* On some architectures dladdr can't use st_size of all symbols this way. */
#define DL_ADDR_SYM_MATCH(L, SYM, MATCHSYM, ADDR) \
((ADDR) >= (L)->l_addr + (SYM)->st_value && \
((((SYM)->st_shndx == SHN_UNDEF || (SYM)->st_size == 0) && \
(ADDR) == (L)->l_addr + (SYM)->st_value) || \
(ADDR) < (L)->l_addr + (SYM)->st_value + (SYM)->st_size) && \
((MATCHSYM) == NULL || (MATCHSYM)->st_value < (SYM)->st_value))
/* According to the ELF gABI no STV_HIDDEN or STV_INTERNAL symbols are
expected to be present in dynamic symbol tables as they should have
been either removed or converted to STB_LOCAL binding by the static
linker. However some GNU binutils versions produce such symbols in
some cases. To prevent such symbols present in a buggy binary from
preempting global symbols we filter them out with this predicate. */
static __always_inline bool dl_symbol_visibility_binds_local_p(const ElfW(Sym) *
sym) {
return (ELFW(ST_VISIBILITY)(sym->st_other) == STV_HIDDEN ||
ELFW(ST_VISIBILITY)(sym->st_other) == STV_INTERNAL);
}
/* Unmap a loaded object, called by _dl_close (). */
#ifndef DL_UNMAP_IS_SPECIAL
#define DL_UNMAP(map) _dl_unmap_segments(map)
#endif
/* Reloc type classes as returned by elf_machine_type_class().
ELF_RTYPE_CLASS_PLT means this reloc should not be satisfied by
some PLT symbol, ELF_RTYPE_CLASS_COPY means this reloc should not be
satisfied by any symbol in the executable. Some architectures do
not support copy relocations. In this case we define the macro to
zero so that the code for handling them gets automatically optimized
out. ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA means address of protected
data defined in the shared library may be external, i.e., due to copy
relocation. */
#define ELF_RTYPE_CLASS_PLT 1
#ifndef DL_NO_COPY_RELOCS
#define ELF_RTYPE_CLASS_COPY 2
#else
#define ELF_RTYPE_CLASS_COPY 0
#endif
/* If DL_EXTERN_PROTECTED_DATA is defined, address of protected data
defined in the shared library may be external, i.e., due to copy
relocation. */
#ifdef DL_EXTERN_PROTECTED_DATA
#define ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA 4
#else
#define ELF_RTYPE_CLASS_EXTERN_PROTECTED_DATA 0
#endif
/* ELF uses the PF_x macros to specify the segment permissions, mmap
uses PROT_xxx. In most cases the three macros have the values 1, 2,
and 3 but not in a matching order. The following macros allows
converting from the PF_x values to PROT_xxx values. */
#define PF_TO_PROT \
((PROT_READ << (PF_R * 4)) | (PROT_WRITE << (PF_W * 4)) | \
(PROT_EXEC << (PF_X * 4)) | \
((PROT_READ | PROT_WRITE) << ((PF_R | PF_W) * 4)) | \
((PROT_READ | PROT_EXEC) << ((PF_R | PF_X) * 4)) | \
((PROT_WRITE | PROT_EXEC) << (PF_W | PF_X) * 4) | \
((PROT_READ | PROT_WRITE | PROT_EXEC) << ((PF_R | PF_W | PF_X) * 4)))
/* The filename itself, or the main program name, if available. */
#define DSO_FILENAME(name) \
((name)[0] ? (name) : (rtld_progname ?: "<main program>"))
#define RTLD_PROGNAME (rtld_progname ?: "<program name unknown>")
/* For the version handling we need an array with only names and their
hash values. */
struct r_found_version {
const char *name;
ElfW(Word) hash;
int hidden;
const char *filename;
};
/* We want to cache information about the searches for shared objects. */
enum r_dir_status { unknown, nonexisting, existing };
struct r_search_path_elem {
/* This link is only used in the `all_dirs' member of `r_search_path'. */
struct r_search_path_elem *next;
/* Strings saying where the definition came from. */
const char *what;
const char *where;
/* Basename for this search path element. The string must end with
a slash character. */
const char *dirname;
size_t dirnamelen;
enum r_dir_status status[0];
};
struct r_strlenpair {
const char *str;
size_t len;
};
/* A data structure for a simple single linked list of strings. */
struct libname_list {
const char *name; /* Name requested (before search). */
struct libname_list *next; /* Link to next name for this object. */
int dont_free; /* Flag whether this element should be freed
if the object is not entirely unloaded. */
};
/* Bit masks for the objects which valid callers can come from to
functions with restricted interface. */
enum allowmask {
allow_libc = 1,
allow_libdl = 2,
allow_libpthread = 4,
allow_ldso = 8
};
/* DSO sort algorithm to use (check dl-sort-maps.c). */
enum dso_sort_algorithm { dso_sort_algorithm_original, dso_sort_algorithm_dfs };
struct audit_ifaces {
void (*activity)(uintptr_t *, unsigned int);
char *(*objsearch)(const char *, uintptr_t *, unsigned int);
unsigned int (*objopen)(struct link_map *, Lmid_t, uintptr_t *);
void (*preinit)(uintptr_t *);
union {
uintptr_t (*symbind32)(Elf32_Sym *, unsigned int, uintptr_t *,
uintptr_t *, unsigned int *, const char *);
uintptr_t (*symbind64)(Elf64_Sym *, unsigned int, uintptr_t *,
uintptr_t *, unsigned int *, const char *);
};
union {
#ifdef ARCH_PLTENTER_MEMBERS
ARCH_PLTENTER_MEMBERS;
#endif
};
union {
#ifdef ARCH_PLTEXIT_MEMBERS
ARCH_PLTEXIT_MEMBERS;
#endif
};
unsigned int (*objclose)(uintptr_t *);
struct audit_ifaces *next;
};
/* Test whether given NAME matches any of the names of the given object. */
extern int _dl_name_match_p(const char *__name,
const struct link_map *__map) attribute_hidden;
/* Compute next higher prime number. */
extern unsigned long int _dl_higher_prime_number(unsigned long int n)
attribute_hidden;
/* A stripped down strtoul-like implementation. */
uint64_t _dl_strtoul(const char *, char **) attribute_hidden;
/* Function used as argument for `_dl_receive_error' function. The
arguments are the error code, error string, and the objname the
error occurred in. */
typedef void (*receiver_fct)(int, const char *, const char *);
// TODO (akawashiro)
struct link_map {
/* These first few members are part of the protocol with the debugger.
This is the same format used in SVR4. */
ElfW(Addr) l_addr; /* Difference between the address in the ELF
file and the addresses in memory. */
char *l_name; /* Absolute file name object was found in. */
ElfW(Dyn) * l_ld; /* Dynamic section of the shared object. */
struct link_map *l_next, *l_prev; /* Chain of loaded objects. */
/* All following members are internal to the dynamic linker.
They may change without notice. */
/* This is an element which is only ever different from a pointer to
the very same copy of this type for ld.so when it is used in more
than one namespace. */
struct link_map *l_real;
/* Number of the namespace this link map belongs to. */
Lmid_t l_ns;
struct libname_list *l_libname;
/* Indexed pointers to dynamic section.
[0,DT_NUM) are indexed by the processor-independent tags.
[DT_NUM,DT_NUM+DT_THISPROCNUM) are indexed by the tag minus DT_LOPROC.
[DT_NUM+DT_THISPROCNUM,DT_NUM+DT_THISPROCNUM+DT_VERSIONTAGNUM) are
indexed by DT_VERSIONTAGIDX(tagvalue).
[DT_NUM+DT_THISPROCNUM+DT_VERSIONTAGNUM,
DT_NUM+DT_THISPROCNUM+DT_VERSIONTAGNUM+DT_EXTRANUM) are indexed by
DT_EXTRATAGIDX(tagvalue).
[DT_NUM+DT_THISPROCNUM+DT_VERSIONTAGNUM+DT_EXTRANUM,
DT_NUM+DT_THISPROCNUM+DT_VERSIONTAGNUM+DT_EXTRANUM+DT_VALNUM) are
indexed by DT_VALTAGIDX(tagvalue) and
[DT_NUM+DT_THISPROCNUM+DT_VERSIONTAGNUM+DT_EXTRANUM+DT_VALNUM,
DT_NUM+DT_THISPROCNUM+DT_VERSIONTAGNUM+DT_EXTRANUM+DT_VALNUM+DT_ADDRNUM)
are indexed by DT_ADDRTAGIDX(tagvalue), see <elf.h>. */
ElfW(Dyn) * l_info[DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM +
DT_EXTRANUM + DT_VALNUM + DT_ADDRNUM];
const ElfW(Phdr) * l_phdr; /* Pointer to program header table in core. */
ElfW(Addr) l_entry; /* Entry point location. */
ElfW(Half) l_phnum; /* Number of program header entries. */
ElfW(Half) l_ldnum; /* Number of dynamic segment entries. */
/* Array of DT_NEEDED dependencies and their dependencies, in
dependency order for symbol lookup (with and without
duplicates). There is no entry before the dependencies have
been loaded. */
struct r_scope_elem l_searchlist;
/* We need a special searchlist to process objects marked with
DT_SYMBOLIC. */
struct r_scope_elem l_symbolic_searchlist;
/* Dependent object that first caused this object to be loaded. */
struct link_map *l_loader;
/* Array with version names. */
struct r_found_version *l_versions;
unsigned int l_nversions;
/* Symbol hash table. */
Elf_Symndx l_nbuckets;
Elf32_Word l_gnu_bitmask_idxbits;
Elf32_Word l_gnu_shift;
const ElfW(Addr) * l_gnu_bitmask;
union {
const Elf32_Word *l_gnu_buckets;
const Elf_Symndx *l_chain;
};
union {
const Elf32_Word *l_gnu_chain_zero;
const Elf_Symndx *l_buckets;
};
unsigned int l_direct_opencount; /* Reference count for dlopen/dlclose. */
enum /* Where this object came from. */
{
lt_executable, /* The main executable program. */
lt_library, /* Library needed by main executable. */
lt_loaded /* Extra run-time loaded shared object. */
} l_type : 2;
unsigned int l_relocated : 1; /* Nonzero if object's relocations done. */
unsigned int l_init_called : 1; /* Nonzero if DT_INIT function called. */
unsigned int l_global : 1; /* Nonzero if object in _dl_global_scope. */
unsigned int l_reserved : 2; /* Reserved for internal use. */
unsigned int l_main_map : 1; /* Nonzero for the map of the main program. */
unsigned int l_visited : 1; /* Used internally for map dependency
graph traversal. */
unsigned int l_map_used : 1; /* These two bits are used during traversal */
unsigned int l_map_done : 1; /* of maps in _dl_close_worker. */
unsigned int l_phdr_allocated : 1; /* Nonzero if the data structure pointed
to by `l_phdr' is allocated. */
unsigned int l_soname_added : 1; /* Nonzero if the SONAME is for sure in
the l_libname list. */
unsigned int l_faked : 1; /* Nonzero if this is a faked descriptor
without associated file. */
unsigned int l_need_tls_init : 1; /* Nonzero if GL(dl_init_static_tls)
should be called on this link map
when relocation finishes. */
unsigned int l_auditing : 1; /* Nonzero if the DSO is used in auditing. */
unsigned int
l_audit_any_plt : 1; /* Nonzero if at least one audit module
is interested in the PLT interception.*/
unsigned int l_removed : 1; /* Nozero if the object cannot be used anymore
since it is removed. */
unsigned int l_contiguous : 1; /* Nonzero if inter-segment holes are
mprotected or if no holes are present at
all. */
unsigned int l_symbolic_in_local_scope : 1; /* Nonzero if l_local_scope
during LD_TRACE_PRELINKING=1
contains any DT_SYMBOLIC
libraries. */
unsigned int l_free_initfini : 1; /* Nonzero if l_initfini can be
freed, ie. not allocated with
the dummy malloc in ld.so. */
unsigned int
l_ld_readonly : 1; /* Nonzero if dynamic section is readonly. */
unsigned int l_find_object_processed : 1; /* Zero if _dl_find_object_update
needs to process this
lt_library map. */
/* NODELETE status of the map. Only valid for maps of type
lt_loaded. Lazy binding sets l_nodelete_active directly,
potentially from signal handlers. Initial loading of an
DF_1_NODELETE object set l_nodelete_pending. Relocation may
set l_nodelete_pending as well. l_nodelete_pending maps are
promoted to l_nodelete_active status in the final stages of
dlopen, prior to calling ELF constructors. dlclose only
refuses to unload l_nodelete_active maps, the pending status is
ignored. */
bool l_nodelete_active;
bool l_nodelete_pending;
// TODO (akawashiro)
// #include <link_map.h>
/* if this object has GNU property. */
enum {
lc_property_unknown = 0, /* Unknown property status. */
lc_property_none = 1 << 0, /* No property. */
lc_property_valid = 1 << 1 /* Has valid property. */
} l_property : 2;
/* GNU_PROPERTY_X86_FEATURE_1_AND of this object. */
unsigned int l_x86_feature_1_and;
/* GNU_PROPERTY_X86_ISA_1_NEEDED of this object. */
unsigned int l_x86_isa_1_needed;
// #include <sysdeps/generic/link_map.h>
unsigned int l_1_needed;
/* Collected information about own RPATH directories. */
struct r_search_path_struct l_rpath_dirs;
/* Collected results of relocation while profiling. */
struct reloc_result {
DL_FIXUP_VALUE_TYPE addr;
struct link_map *bound;
unsigned int boundndx;
uint32_t enterexit;
unsigned int flags;
/* CONCURRENCY NOTE: This is used to guard the concurrent initialization
of the relocation result across multiple threads. See the more
detailed notes in elf/dl-runtime.c. */
unsigned int init;
} * l_reloc_result;
/* Pointer to the version information if available. */
ElfW(Versym) * l_versyms;
/* String specifying the path where this object was found. */
const char *l_origin;
/* Start and finish of memory map for this object. l_map_start
need not be the same as l_addr. */
ElfW(Addr) l_map_start, l_map_end;
/* End of the executable part of the mapping. */
ElfW(Addr) l_text_end;
/* Default array for 'l_scope'. */
struct r_scope_elem *l_scope_mem[4];
/* Size of array allocated for 'l_scope'. */
size_t l_scope_max;
/* This is an array defining the lookup scope for this link map.
There are initially at most three different scope lists. */
struct r_scope_elem **l_scope;
/* A similar array, this time only with the local scope. This is
used occasionally. */
struct r_scope_elem *l_local_scope[2];
/* This information is kept to check for sure whether a shared
object is the same as one already loaded. */
struct r_file_id l_file_id;
/* Collected information about own RUNPATH directories. */
struct r_search_path_struct l_runpath_dirs;
/* List of object in order of the init and fini calls. */
struct link_map **l_initfini;
/* List of the dependencies introduced through symbol binding. */
struct link_map_reldeps {
unsigned int act;
struct link_map *list[];
} * l_reldeps;
unsigned int l_reldepsmax;
/* Nonzero if the DSO is used. */
unsigned int l_used;
/* Various flag words. */
ElfW(Word) l_feature_1;
ElfW(Word) l_flags_1;
ElfW(Word) l_flags;
/* Temporarily used in `dl_close'. */
int l_idx;
struct link_map_machine l_mach;
struct {
const ElfW(Sym) * sym;
int type_class;
struct link_map *value;
const ElfW(Sym) * ret;
} l_lookup_cache;
/* Thread-local storage related info. */
/* Start of the initialization image. */
void *l_tls_initimage;
/* Size of the initialization image. */
size_t l_tls_initimage_size;
/* Size of the TLS block. */
size_t l_tls_blocksize;
/* Alignment requirement of the TLS block. */
size_t l_tls_align;
/* Offset of first byte module alignment. */
size_t l_tls_firstbyte_offset;
#ifndef NO_TLS_OFFSET
#define NO_TLS_OFFSET 0
#endif
#ifndef FORCED_DYNAMIC_TLS_OFFSET
#if NO_TLS_OFFSET == 0
#define FORCED_DYNAMIC_TLS_OFFSET -1
#elif NO_TLS_OFFSET == -1
#define FORCED_DYNAMIC_TLS_OFFSET -2
#else
#error "FORCED_DYNAMIC_TLS_OFFSET is not defined"
#endif
#endif
/* For objects present at startup time: offset in the static TLS block. */
ptrdiff_t l_tls_offset;
/* Index of the module in the dtv array. */
size_t l_tls_modid;
/* Number of thread_local objects constructed by this DSO. This is
atomically accessed and modified and is not always protected by the load
lock. See also: CONCURRENCY NOTES in cxa_thread_atexit_impl.c. */
size_t l_tls_dtor_count;
/* Information used to change permission after the relocations are
done. */
ElfW(Addr) l_relro_addr;
size_t l_relro_size;
unsigned long long int l_serial;
};
/* Internal functions of the run-time dynamic linker.
These can be accessed if you link again the dynamic linker
as a shared library, as in `-lld' or `/lib/ld.so' explicitly;
but are not normally of interest to user programs.
The `-ldl' library functions in <dlfcn.h> provide a simple
user interface to run-time dynamic linking. */
#ifndef SHARED
#define EXTERN extern
#define GL(name) _##name
#else
#define EXTERN
#if IS_IN(rtld)
#define GL(name) _rtld_local._##name
#else
#define GL(name) _rtld_global._##name
#endif
struct rtld_global {
#endif
/* Don't change the order of the following elements. 'dl_loaded'
must remain the first element. Forever. */
/* Non-shared code has no support for multiple namespaces. */
#ifdef SHARED
#define DL_NNS 16
#else
#define DL_NNS 1
#endif
EXTERN struct link_namespaces {
/* A pointer to the map for the main map. */
struct link_map *_ns_loaded;
/* Number of object in the _dl_loaded list. */
unsigned int _ns_nloaded;
/* Direct pointer to the searchlist of the main object. */
struct r_scope_elem *_ns_main_searchlist;
/* This is zero at program start to signal that the global scope map is
allocated by rtld. Later it keeps the size of the map. It might be
reset if in _dl_close if the last global object is removed. */
unsigned int _ns_global_scope_alloc;
/* During dlopen, this is the number of objects that still need to
be added to the global scope map. It has to be taken into
account when resizing the map, for future map additions after
recursive dlopen calls from ELF constructors. */
unsigned int _ns_global_scope_pending_adds;
/* Once libc.so has been loaded into the namespace, this points to
its link map. */
struct link_map *libc_map;
/* Search table for unique objects. */
// TODO (akawashiro)
// struct unique_sym_table {
// __rtld_lock_define_recursive(, lock) struct unique_sym {
// uint32_t hashval;
// const char *name;
// const ElfW(Sym) * sym;
// const struct link_map *map;
// } * entries;
// size_t size;
// size_t n_elements;
// void (*free)(void *);
// } _ns_unique_sym_table;
/* Keep track of changes to each namespace' list. */
struct r_debug_extended _ns_debug;
} _dl_ns[DL_NNS];
/* One higher than index of last used namespace. */
EXTERN size_t _dl_nns;
/* During the program run we must not modify the global data of
loaded shared object simultanously in two threads. Therefore we
protect `_dl_open' and `_dl_close' in dl-close.c.
This must be a recursive lock since the initializer function of
the loaded object might as well require a call to this function.
At this time it is not anymore a problem to modify the tables. */
// TODO (akawashiro)
// __rtld_lock_define_recursive(EXTERN, _dl_load_lock)
/* This lock is used to keep __dl_iterate_phdr from inspecting the
list of loaded objects while an object is added to or removed
from that list. */
// TODO (akawashiro)
// __rtld_lock_define_recursive(EXTERN, _dl_load_write_lock)
/* This lock protects global and module specific TLS related data.
E.g. it is held in dlopen and dlclose when GL(dl_tls_generation),
GL(dl_tls_max_dtv_idx) or GL(dl_tls_dtv_slotinfo_list) are
accessed and when TLS related relocations are processed for a
module. It was introduced to keep pthread_create accessing TLS
state that is being set up. */
// TODO (akawashiro)
// __rtld_lock_define_recursive(EXTERN, _dl_load_tls_lock)
/* Incremented whenever something may have been added to dl_loaded. */
EXTERN unsigned long long _dl_load_adds;
/* The object to be initialized first. */
EXTERN struct link_map *_dl_initfirst;
/* Map of shared object to be profiled. */
EXTERN struct link_map *_dl_profile_map;
/* Counters for the number of relocations performed. */
EXTERN unsigned long int _dl_num_relocations;
EXTERN unsigned long int _dl_num_cache_relocations;
/* List of search directories. */
EXTERN struct r_search_path_elem *_dl_all_dirs;
/* Structure describing the dynamic linker itself. */
EXTERN struct link_map _dl_rtld_map;
#ifdef SHARED
/* Used to store the audit information for the link map of the
dynamic loader. */
struct auditstate _dl_rtld_auditstate[DL_NNS];
#endif
#if !PTHREAD_IN_LIBC && defined SHARED && \
defined __rtld_lock_default_lock_recursive
EXTERN void (*_dl_rtld_lock_recursive)(void *);
EXTERN void (*_dl_rtld_unlock_recursive)(void *);
#endif
/* Get architecture specific definitions. */
#define PROCINFO_DECL
#ifndef PROCINFO_CLASS
#define PROCINFO_CLASS EXTERN
#endif
// TODO (akawashiro)
// #include <dl-procruntime.c>
#if !PTHREAD_IN_LIBC
/* If loading a shared object requires that we make the stack executable
when it was not, we do it by calling this function.
It returns an errno code or zero on success. */
EXTERN int (*_dl_make_stack_executable_hook)(void **);
#endif
/* Prevailing state of the stack, PF_X indicating it's executable. */
EXTERN ElfW(Word) _dl_stack_flags;
/* Flag signalling whether there are gaps in the module ID allocation. */
EXTERN bool _dl_tls_dtv_gaps;
/* Highest dtv index currently needed. */
EXTERN size_t _dl_tls_max_dtv_idx;
/* Information about the dtv slots. */
EXTERN struct dtv_slotinfo_list {
size_t len;
struct dtv_slotinfo_list *next;
struct dtv_slotinfo {
size_t gen;
struct link_map *map;
} slotinfo[];
} * _dl_tls_dtv_slotinfo_list;
/* Number of modules in the static TLS block. */
EXTERN size_t _dl_tls_static_nelem;
/* Size actually allocated in the static TLS block. */
EXTERN size_t _dl_tls_static_used;
/* Remaining amount of static TLS that may be used for optimizing
dynamic TLS access (e.g. with TLSDESC). */
EXTERN size_t _dl_tls_static_optional;
/* Number of additional entries in the slotinfo array of each slotinfo
list element. A large number makes it almost certain take we never
have to iterate beyond the first element in the slotinfo list. */
#define TLS_SLOTINFO_SURPLUS (62)
/* Number of additional slots in the dtv allocated. */
#define DTV_SURPLUS (14)
/* Initial dtv of the main thread, not allocated with normal malloc. */
EXTERN void *_dl_initial_dtv;
/* Generation counter for the dtv. */
EXTERN size_t _dl_tls_generation;
#if !PTHREAD_IN_LIBC
EXTERN void (*_dl_init_static_tls)(struct link_map *);
#endif
/* Scopes to free after next THREAD_GSCOPE_WAIT (). */
EXTERN struct dl_scope_free_list {
size_t count;
void *list[50];
} * _dl_scope_free_list;
#if PTHREAD_IN_LIBC
/* List of active thread stacks, with memory managed by glibc. */
EXTERN list_t _dl_stack_used;
/* List of thread stacks that were allocated by the application. */
EXTERN list_t _dl_stack_user;
/* List of queued thread stacks. */
EXTERN list_t _dl_stack_cache;
/* Total size of all stacks in the cache (sum over stackblock_size). */
EXTERN size_t _dl_stack_cache_actsize;
/* We need to record what list operations we are going to do so
that, in case of an asynchronous interruption due to a fork()
call, we can correct for the work. */
EXTERN uintptr_t _dl_in_flight_stack;
/* Mutex protecting the stack lists. */
EXTERN int _dl_stack_cache_lock;
#else
/* The total number of thread IDs currently in use, or on the list of
available thread IDs. */
EXTERN int _dl_pthread_num_threads;
/* Array of __pthread structures and its lock. */
EXTERN struct __pthread **_dl_pthread_threads;
// TODO (akawashiro)
// __libc_rwlock_define(EXTERN, _dl_pthread_threads_lock)
#endif
#ifdef SHARED
}
;
#define __rtld_global_attribute__
#if IS_IN(rtld)
#ifdef HAVE_SDATA_SECTION
#define __rtld_local_attribute__ \
__attribute__((visibility("hidden"), section(".sdata")))
#undef __rtld_global_attribute__
#define __rtld_global_attribute__ __attribute__((section(".sdata")))
#else
#define __rtld_local_attribute__ __attribute__((visibility("hidden")))
#endif
extern struct rtld_global _rtld_local __rtld_local_attribute__;
#undef __rtld_local_attribute__
#endif
extern struct rtld_global _rtld_global __rtld_global_attribute__;
#undef __rtld_global_attribute__
#endif
#ifndef SHARED
#define GLRO(name) _##name
#else
#if IS_IN(rtld)
#define GLRO(name) _rtld_local_ro._##name
#else
#define GLRO(name) _rtld_global_ro._##name
#endif
struct rtld_global_ro {
#endif
/* If nonzero the appropriate debug information is printed. */
EXTERN int _dl_debug_mask;
#define DL_DEBUG_LIBS (1 << 0)
#define DL_DEBUG_IMPCALLS (1 << 1)
#define DL_DEBUG_BINDINGS (1 << 2)
#define DL_DEBUG_SYMBOLS (1 << 3)
#define DL_DEBUG_VERSIONS (1 << 4)
#define DL_DEBUG_RELOC (1 << 5)
#define DL_DEBUG_FILES (1 << 6)
#define DL_DEBUG_STATISTICS (1 << 7)
#define DL_DEBUG_UNUSED (1 << 8)
#define DL_DEBUG_SCOPES (1 << 9)
/* These two are used only internally. */
#define DL_DEBUG_HELP (1 << 10)
#define DL_DEBUG_PRELINK (1 << 11)
/* OS version. */
EXTERN unsigned int _dl_osversion;
/* Platform name. */
EXTERN const char *_dl_platform;
EXTERN size_t _dl_platformlen;
/* Cached value of `getpagesize ()'. */
EXTERN size_t _dl_pagesize;
/* Cached value of `sysconf (_SC_MINSIGSTKSZ)'. */
EXTERN size_t _dl_minsigstacksize;
/* Do we read from ld.so.cache? */
EXTERN int _dl_inhibit_cache;
/* Copy of the content of `_dl_main_searchlist' at startup time. */
// TODO (akawashiro)
// EXTERN struct r_scope_elem _dl_initial_searchlist;
/* CLK_TCK as reported by the kernel. */
EXTERN int _dl_clktck;
/* If nonzero print warnings messages. */
EXTERN int _dl_verbose;
/* File descriptor to write debug messages to. */
EXTERN int _dl_debug_fd;
/* Do we do lazy relocations? */
EXTERN int _dl_lazy;
/* Nonzero if runtime lookups should not update the .got/.plt. */
EXTERN int _dl_bind_not;
/* Nonzero if references should be treated as weak during runtime
linking. */
EXTERN int _dl_dynamic_weak;
/* Default floating-point control word. */
EXTERN fpu_control_t _dl_fpu_control;
/* Expected cache ID. */
EXTERN int _dl_correct_cache_id;
/* Mask for hardware capabilities that are available. */
EXTERN uint64_t _dl_hwcap;
#if !HAVE_TUNABLES
/* Mask for important hardware capabilities we honour. */
EXTERN uint64_t _dl_hwcap_mask;
#endif
#ifdef HAVE_AUX_VECTOR
/* Pointer to the auxv list supplied to the program at startup. */
EXTERN ElfW(auxv_t) * _dl_auxv;
#endif
/* Get architecture specific definitions. */
// TODO (akawashiro)
// #include <dl-procinfo.c>
/* Names of shared object for which the RPATH should be ignored. */
EXTERN const char *_dl_inhibit_rpath;
/* Location of the binary. */
EXTERN const char *_dl_origin_path;
/* -1 if the dynamic linker should honor library load bias,
0 if not, -2 use the default (honor biases for normal
binaries, don't honor for PIEs). */
EXTERN ElfW(Addr) _dl_use_load_bias;
/* Size of the static TLS block. */
EXTERN size_t _dl_tls_static_size;
/* Alignment requirement of the static TLS block. */
EXTERN size_t _dl_tls_static_align;
/* Size of surplus space in the static TLS area for dynamically
loaded modules with IE-model TLS or for TLSDESC optimization.
See comments in elf/dl-tls.c where it is initialized. */