History

text relocation for netbsd

netbsd does not allow text relocations in text segment. tcc.h: - Add data_ro_section - Fix typo rela.plt tccelf.c: - Add data_ro_section - Make bounds_section/lbounds_section rw - Add GNU_RELRO section for data_ro_section/bounds_section/lbounds_section - Fix relocation for __dso_handle in atexit() tccgen.c: - Use data_ro_section x86_64-gen.c: - Use R_X86_64_PC32 instead of R_X86_64_64 for bounds checking tests/Makefile, tests/tests2/Makefile - Enable dll tests for netbsd

herman ten brugge committed 5 years ago

Commit 08219401 parent c13c4346 files · +101 −44Browse files

Unified · Split

6 files
  1. tcc.h +3 −2
  2. tccelf.c +86 −23
  3. tccgen.c +4 −2
  4. tests/Makefile +1 −7
  5. tests/tests2/Makefile +0 −3
  6. x86_64-gen.c +7 −7
tcc.h+3−2
@@ -409,7 +409,7 @@ extern long double strtold (const char *__nptr, char **__endptr); · 408 unmodified lines
409# define ElfW_Rel ElfW(Rela)409# define ElfW_Rel ElfW(Rela)
410# define SHT_RELX SHT_RELA410# define SHT_RELX SHT_RELA
411# define REL_SECTION_FMT ".rela%s"411# define REL_SECTION_FMT ".rela%s"
412# define RELPLT_SECTION_FMT ".rel.plt"412# define RELPLT_SECTION_FMT ".rela.plt"
413#else413#else
414# define ELFCLASSW ELFCLASS32414# define ELFCLASSW ELFCLASS32
415# define ElfW(type) Elf##32##_##type415# define ElfW(type) Elf##32##_##type
@@ -872,7 +872,7 @@ struct TCCState { · 456 unmodified lines
872 Section *plt;872 Section *plt;
873 873
874 /* predefined sections */874 /* predefined sections */
875 Section *text_section, *data_section, *bss_section;875 Section *text_section, *data_section, *data_ro_section, *bss_section;
876 Section *common_section;876 Section *common_section;
877 Section *cur_text_section; /* current section where function code is generated */877 Section *cur_text_section; /* current section where function code is generated */
878#ifdef CONFIG_TCC_BCHECK878#ifdef CONFIG_TCC_BCHECK
@@ -1817,6 +1817,7 @@ ST_FUNC void gen_makedeps(TCCState *s, const char *target, const char *filename) · 938 unmodified lines
1817 1817
1818#define text_section TCC_STATE_VAR(text_section)1818#define text_section TCC_STATE_VAR(text_section)
1819#define data_section TCC_STATE_VAR(data_section)1819#define data_section TCC_STATE_VAR(data_section)
1820#define data_ro_section TCC_STATE_VAR(data_ro_section)
1820#define bss_section TCC_STATE_VAR(bss_section)1821#define bss_section TCC_STATE_VAR(bss_section)
1821#define common_section TCC_STATE_VAR(common_section)1822#define common_section TCC_STATE_VAR(common_section)
1822#define cur_text_section TCC_STATE_VAR(cur_text_section)1823#define cur_text_section TCC_STATE_VAR(cur_text_section)
tccelf.c+86−23
@@ -58,6 +58,8 @@ ST_FUNC void tccelf_new(TCCState *s) · 57 unmodified lines
58 /* create standard sections */58 /* create standard sections */
59 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);59 text_section = new_section(s, ".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR);
60 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);60 data_section = new_section(s, ".data", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
61 /* create ro data section (make ro after relocation done with GNU_RELRO) */
62 data_ro_section = new_section(s, ".data.ro", SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
61 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);63 bss_section = new_section(s, ".bss", SHT_NOBITS, SHF_ALLOC | SHF_WRITE);
62 common_section = new_section(s, ".common", SHT_NOBITS, SHF_PRIVATE);64 common_section = new_section(s, ".common", SHT_NOBITS, SHF_PRIVATE);
63 common_section->sh_num = SHN_COMMON;65 common_section->sh_num = SHN_COMMON;
@@ -79,11 +81,11 @@ ST_FUNC void tccelf_new(TCCState *s) · 15 unmodified lines
79ST_FUNC void tccelf_bounds_new(TCCState *s)81ST_FUNC void tccelf_bounds_new(TCCState *s)
80{82{
81 TCCState *s1 = s;83 TCCState *s1 = s;
82 /* create bounds sections */84 /* create bounds sections (make ro after relocation done with GNU_RELRO) */
83 bounds_section = new_section(s, ".bounds",85 bounds_section = new_section(s, ".bounds",
84 SHT_PROGBITS, SHF_ALLOC);86 SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
85 lbounds_section = new_section(s, ".lbounds",87 lbounds_section = new_section(s, ".lbounds",
86 SHT_PROGBITS, SHF_ALLOC);88 SHT_PROGBITS, SHF_ALLOC | SHF_WRITE);
87}89}
88#endif90#endif
89 91
@@ -1043,6 +1045,16 @@ static int prepare_dynamic_rel(TCCState *s1, Section *sr) · 953 unmodified lines
1043 case R_386_PC32:1045 case R_386_PC32:
1044#elif defined(TCC_TARGET_X86_64)1046#elif defined(TCC_TARGET_X86_64)
1045 case R_X86_64_PC32:1047 case R_X86_64_PC32:
1048 {
1049 ElfW(Sym) *sym = &((ElfW(Sym) *)symtab_section->data)[sym_index];
1050
1051 /* support __dso_handle in atexit() */
1052 if (sym->st_shndx != SHN_UNDEF &&
1053 ELFW(ST_VISIBILITY)(sym->st_other) == STV_HIDDEN) {
1054 rel->r_info = ELFW(R_INFO)(sym_index, R_X86_64_PLT32);
1055 break;
1056 }
1057 }
1046#elif defined(TCC_TARGET_ARM64)1058#elif defined(TCC_TARGET_ARM64)
1047 case R_AARCH64_PREL32:1059 case R_AARCH64_PREL32:
1048#endif1060#endif
@@ -1828,11 +1840,20 @@ struct dyn_inf { · 779 unmodified lines
1828 addr_t rel_size;1840 addr_t rel_size;
1829};1841};
1830 1842
1843/* Info for GNU_RELRO */
1844struct ro_inf {
1845 addr_t sh_offset;
1846 addr_t sh_addr;
1847 addr_t sh_size;
1848};
1849
1831/* Assign sections to segments and decide how are sections laid out when loaded1850/* Assign sections to segments and decide how are sections laid out when loaded
1832 in memory. This function also fills corresponding program headers. */1851 in memory. This function also fills corresponding program headers. */
1833static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum,1852static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr,
1853 int phnum, int phfill,
1834 Section *interp, Section* strsec,1854 Section *interp, Section* strsec,
1835 struct dyn_inf *dyninf, int *sec_order)1855 struct dyn_inf *dyninf, struct ro_inf *roinf,
1856 int *sec_order)
1836{1857{
1837 int i, sh_order_index, file_offset;1858 int i, sh_order_index, file_offset;
1838 Section *s;1859 Section *s;
@@ -1883,7 +1904,10 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum, · 44 unmodified lines
1883 /* dynamic relocation table information, for .dynamic section */1904 /* dynamic relocation table information, for .dynamic section */
1884 dyninf->rel_addr = dyninf->rel_size = 0;1905 dyninf->rel_addr = dyninf->rel_size = 0;
1885 1906
1886 for(j = 0; j < (phnum == 6 ? 3 : 2); j++) {1907 /* read only segment mapping for GNU_RELRO */
1908 roinf->sh_offset = roinf->sh_addr = roinf->sh_size = 0;
1909
1910 for(j = 0; j < phfill; j++) {
1887 Section *relocplt = s1->got ? s1->got->relocplt : NULL;1911 Section *relocplt = s1->got ? s1->got->relocplt : NULL;
1888 1912
1889 ph->p_type = j == 2 ? PT_TLS : PT_LOAD;1913 ph->p_type = j == 2 ? PT_TLS : PT_LOAD;
@@ -1898,7 +1922,7 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum, · 8 unmodified lines
1898 info about the layout. We do the following ordering: interp,1922 info about the layout. We do the following ordering: interp,
1899 symbol tables, relocations, progbits, nobits */1923 symbol tables, relocations, progbits, nobits */
1900 /* XXX: do faster and simpler sorting */1924 /* XXX: do faster and simpler sorting */
1901 for(k = 0; k < 6; k++) {1925 for(k = 0; k < 7; k++) {
1902 for(i = 1; i < s1->nb_sections; i++) {1926 for(i = 1; i < s1->nb_sections; i++) {
1903 s = s1->sections[i];1927 s = s1->sections[i];
1904 /* compute if section should be included */1928 /* compute if section should be included */
@@ -1930,12 +1954,17 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum, · 25 unmodified lines
1930 else if (k != 3 && s == relocplt)1954 else if (k != 3 && s == relocplt)
1931 continue;1955 continue;
1932 } else if (s->sh_type == SHT_NOBITS) {1956 } else if (s->sh_type == SHT_NOBITS) {
1933 if (k != 5)1957 if (k != 6)
1934 continue;1958 continue;
1935 } else {1959 } else if (s == data_ro_section ||
1960 s == bounds_section ||
1961 s == lbounds_section) {
1936 if (k != 4)1962 if (k != 4)
1937 continue;1963 continue;
1938 }1964 } else {
1965 if (k != 5)
1966 continue;
1967 }
1939 sec_order[sh_order_index++] = i;1968 sec_order[sh_order_index++] = i;
1940 1969
1941 /* section matches: we align it and add its size */1970 /* section matches: we align it and add its size */
@@ -1956,8 +1985,17 @@ static int layout_sections(TCCState *s1, ElfW(Phdr) *phdr, int phnum, · 14 unmodified lines
1956 if (s->sh_type == SHT_RELX && s != relocplt) {1985 if (s->sh_type == SHT_RELX && s != relocplt) {
1957 if (dyninf->rel_size == 0)1986 if (dyninf->rel_size == 0)
1958 dyninf->rel_addr = addr;1987 dyninf->rel_addr = addr;
1959 dyninf->rel_size += s->sh_size;1988 dyninf->rel_size = (addr - dyninf->rel_addr) + s->sh_size;
1960 }1989 }
1990 if (s == data_ro_section ||
1991 s == bounds_section ||
1992 s == lbounds_section) {
1993 if (roinf->sh_size == 0) {
1994 roinf->sh_offset = s->sh_offset;
1995 roinf->sh_addr = s->sh_addr;
1996 }
1997 roinf->sh_size = (addr - roinf->sh_addr) + s->sh_size;
1998 }
1961 addr += s->sh_size;1999 addr += s->sh_size;
1962 if (s->sh_type != SHT_NOBITS)2000 if (s->sh_type != SHT_NOBITS)
1963 file_offset += s->sh_size;2001 file_offset += s->sh_size;
@@ -2018,7 +2056,7 @@ static void put_dt(Section *dynamic, int dt, addr_t val) · 54 unmodified lines
2018}2056}
2019 2057
2020static void fill_unloadable_phdr(ElfW(Phdr) *phdr, int phnum, Section *interp,2058static void fill_unloadable_phdr(ElfW(Phdr) *phdr, int phnum, Section *interp,
2021 Section *dynamic, Section *note)2059 Section *dynamic, Section *note, struct ro_inf *roinf)
2022{2060{
2023 ElfW(Phdr) *ph;2061 ElfW(Phdr) *ph;
2024 2062
@@ -2046,7 +2084,7 @@ static void fill_unloadable_phdr(ElfW(Phdr) *phdr, int phnum, Section *interp, · 21 unmodified lines
2046 }2084 }
2047 2085
2048 if (note) {2086 if (note) {
2049 ph = &phdr[phnum - 2];2087 ph = &phdr[phnum - 2 - (roinf != NULL)];
2050 2088
2051 ph->p_type = PT_NOTE;2089 ph->p_type = PT_NOTE;
2052 ph->p_offset = note->sh_offset;2090 ph->p_offset = note->sh_offset;
@@ -2060,7 +2098,7 @@ static void fill_unloadable_phdr(ElfW(Phdr) *phdr, int phnum, Section *interp, · 7 unmodified lines
2060 2098
2061 /* if dynamic section, then add corresponding program header */2099 /* if dynamic section, then add corresponding program header */
2062 if (dynamic) {2100 if (dynamic) {
2063 ph = &phdr[phnum - 1];2101 ph = &phdr[phnum - 1 - (roinf != NULL)];
2064 2102
2065 ph->p_type = PT_DYNAMIC;2103 ph->p_type = PT_DYNAMIC;
2066 ph->p_offset = dynamic->sh_offset;2104 ph->p_offset = dynamic->sh_offset;
@@ -2071,6 +2109,19 @@ static void fill_unloadable_phdr(ElfW(Phdr) *phdr, int phnum, Section *interp, · 4 unmodified lines
2071 ph->p_flags = PF_R | PF_W;2109 ph->p_flags = PF_R | PF_W;
2072 ph->p_align = dynamic->sh_addralign;2110 ph->p_align = dynamic->sh_addralign;
2073 }2111 }
2112
2113 if (roinf) {
2114 ph = &phdr[phnum - 1];
2115
2116 ph->p_type = PT_GNU_RELRO;
2117 ph->p_offset = roinf->sh_offset;
2118 ph->p_vaddr = roinf->sh_addr;
2119 ph->p_paddr = ph->p_vaddr;
2120 ph->p_filesz = roinf->sh_size;
2121 ph->p_memsz = roinf->sh_size;
2122 ph->p_flags = PF_R;
2123 ph->p_align = 1;
2124 }
2074}2125}
2075 2126
2076/* Fill the dynamic section with tags describing the address and size of2127/* Fill the dynamic section with tags describing the address and size of
@@ -2440,8 +2491,9 @@ static Section *create_bsd_note_section(TCCState *s1, · 363 unmodified lines
2440/* XXX: suppress unneeded sections */2491/* XXX: suppress unneeded sections */
2441static int elf_output_file(TCCState *s1, const char *filename)2492static int elf_output_file(TCCState *s1, const char *filename)
2442{2493{
2443 int ret, phnum, shnum, file_type, file_offset, *sec_order;2494 int i, ret, phnum, phfill, shnum, file_type, file_offset, *sec_order;
2444 struct dyn_inf dyninf = {0};2495 struct dyn_inf dyninf = {0};
2496 struct ro_inf roinf, *roinf_use = NULL;
2445 ElfW(Phdr) *phdr;2497 ElfW(Phdr) *phdr;
2446 Section *strsec, *interp, *dynamic, *dynstr, *note = NULL;2498 Section *strsec, *interp, *dynamic, *dynstr, *note = NULL;
2447 2499
@@ -2489,6 +2541,8 @@ static int elf_output_file(TCCState *s1, const char *filename) · 41 unmodified lines
2489 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,2541 s1->dynsym = new_symtab(s1, ".dynsym", SHT_DYNSYM, SHF_ALLOC,
2490 ".dynstr",2542 ".dynstr",
2491 ".hash", SHF_ALLOC);2543 ".hash", SHF_ALLOC);
2544 /* Number of local symbols (readelf complains if not set) */
2545 s1->dynsym->sh_info = 1;
2492 dynstr = s1->dynsym->link;2546 dynstr = s1->dynsym->link;
2493 /* add dynamic section */2547 /* add dynamic section */
2494 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,2548 dynamic = new_section(s1, ".dynamic", SHT_DYNAMIC,
@@ -2556,22 +2610,31 @@ static int elf_output_file(TCCState *s1, const char *filename) · 61 unmodified lines
2556 }2610 }
2557#endif2611#endif
2558 2612
2613 for (i = 1; i < s1->nb_sections &&
2614 !(s1->sections[i]->sh_flags & SHF_TLS); i++);
2615 phfill = 2 + (i < s1->nb_sections);
2616
2559 /* compute number of program headers */2617 /* compute number of program headers */
2560 if (file_type == TCC_OUTPUT_OBJ)2618 if (file_type == TCC_OUTPUT_OBJ)
2561 phnum = 0;2619 phnum = phfill = 0;
2562 else if (file_type == TCC_OUTPUT_DLL)2620 else if (file_type == TCC_OUTPUT_DLL)
2563 phnum = 3;2621 phnum = 3;
2564 else if (s1->static_link)2622 else if (s1->static_link)
2565 phnum = 2;2623 phnum = 2;
2566 else {2624 else {
2567 int i;2625 phnum = 5 + (i < s1->nb_sections);
2568 for (i = 1; i < s1->nb_sections &&
2569 !(s1->sections[i]->sh_flags & SHF_TLS); i++);
2570 phnum = i < s1->nb_sections ? 6 : 5;
2571 }2626 }
2572 2627
2573 phnum += note != NULL;2628 phnum += note != NULL;
2574 2629
2630#if !TARGETOS_FreeBSD && !TARGETOS_NetBSD && !defined(__APPLE__) && !defined(_WIN32)
2631 /* GNU_RELRO */
2632 if (file_type != TCC_OUTPUT_OBJ) {
2633 phnum++;
2634 roinf_use = &roinf;
2635 }
2636#endif
2637
2575 /* allocate program segment headers */2638 /* allocate program segment headers */
2576 phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));2639 phdr = tcc_mallocz(phnum * sizeof(ElfW(Phdr)));
2577 2640
@@ -2583,14 +2646,14 @@ static int elf_output_file(TCCState *s1, const char *filename) · 5 unmodified lines
2583 sec_order[0] = 0;2646 sec_order[0] = 0;
2584 2647
2585 /* compute section to program header mapping */2648 /* compute section to program header mapping */
2586 file_offset = layout_sections(s1, phdr, phnum, interp, strsec, &dyninf,2649 file_offset = layout_sections(s1, phdr, phnum, phfill, interp, strsec,
2587 sec_order);2650 &dyninf, &roinf, sec_order);
2588 2651
2589#ifndef ELF_OBJ_ONLY2652#ifndef ELF_OBJ_ONLY
2590 /* Fill remaining program header and finalize relocation related to dynamic2653 /* Fill remaining program header and finalize relocation related to dynamic
2591 linking. */2654 linking. */
2592 if (file_type != TCC_OUTPUT_OBJ) {2655 if (file_type != TCC_OUTPUT_OBJ) {
2593 fill_unloadable_phdr(phdr, phnum, interp, dynamic, note);2656 fill_unloadable_phdr(phdr, phnum, interp, dynamic, note, roinf_use);
2594 if (dynamic) {2657 if (dynamic) {
2595 ElfW(Sym) *sym;2658 ElfW(Sym) *sym;
2596 dynamic->data_offset = dyninf.data_offset;2659 dynamic->data_offset = dyninf.data_offset;
tccgen.c+4−2
@@ -8120,8 +8120,10 @@ static void decl_initializer_alloc(CType *type, AttributeDef *ad, int r, · 8119 unmodified lines
8120 /* allocate symbol in corresponding section */8120 /* allocate symbol in corresponding section */
8121 sec = ad->section;8121 sec = ad->section;
8122 if (!sec) {8122 if (!sec) {
8123 if (has_init)8123 if (type->t & VT_CONSTANT)
8124 sec = data_section;8124 sec = data_ro_section;
8125 else if (has_init)
8126 sec = data_section;
8125 else if (tcc_state->nocommon)8127 else if (tcc_state->nocommon)
8126 sec = bss_section;8128 sec = bss_section;
8127 }8129 }
tests/Makefile+1−7
@@ -64,17 +64,11 @@ endif · 63 unmodified lines
64ifeq ($(TARGETOS),OpenBSD)64ifeq ($(TARGETOS),OpenBSD)
65dlltest: CFLAGS+=-fno-stack-protector65dlltest: CFLAGS+=-fno-stack-protector
66endif66endif
67ifeq ($(TARGETOS),FreeBSD)67ifneq (,$(filter FreeBSD NetBSD,$(TARGETOS)))
68 # test3 has dlsym problems68 # test3 has dlsym problems
69 TESTS := $(filter-out test3,$(TESTS))69 TESTS := $(filter-out test3,$(TESTS))
70 TESTS += test170 TESTS += test1
71endif71endif
72ifeq ($(TARGETOS),NetBSD)
73 # test3 has dlsym problems
74 # dlltest does not allow text relocations
75 TESTS := $(filter-out test3 dlltest,$(TESTS))
76 TESTS += test1
77endif
78 72
79RUN_TCC = $(NATIVE_DEFINES) -run $(TOPSRC)/tcc.c $(TCCFLAGS)73RUN_TCC = $(NATIVE_DEFINES) -run $(TOPSRC)/tcc.c $(TCCFLAGS)
80DISAS = objdump -d74DISAS = objdump -d
tests/tests2/Makefile+0−3
@@ -53,9 +53,6 @@ ifneq (,$(filter OpenBSD FreeBSD NetBSD,$(TARGETOS))) · 52 unmodified lines
53 SKIP += 114_bound_signal.test # libc problem signal/fork53 SKIP += 114_bound_signal.test # libc problem signal/fork
54 SKIP += 116_bound_setjmp2.test # No TLS_FUNC/TLS_VAR in bcheck.c54 SKIP += 116_bound_setjmp2.test # No TLS_FUNC/TLS_VAR in bcheck.c
55endif55endif
56ifeq ($(TARGETOS),NetBSD)
57 SKIP += 113_btdll.test # text relocations
58endif
59 56
60# Some tests might need arguments57# Some tests might need arguments
61ARGS =58ARGS =
x86_64-gen.c+7−7
@@ -674,8 +674,8 @@ static void gen_bounds_prolog(void) · 673 unmodified lines
674 func_bound_offset = lbounds_section->data_offset;674 func_bound_offset = lbounds_section->data_offset;
675 func_bound_ind = ind;675 func_bound_ind = ind;
676 func_bound_add_epilog = 0;676 func_bound_add_epilog = 0;
677 o(0xb848 + TREG_FASTCALL_1 * 0x100); /*lbound section pointer */677 o(0x0d8d48 + ((TREG_FASTCALL_1 == TREG_RDI) * 0x300000)); /*lbound section pointer */
678 gen_le64 (0);678 gen_le32 (0);
679 oad(0xb8, 0); /* call to function */679 oad(0xb8, 0); /* call to function */
680}680}
681 681
@@ -700,17 +700,17 @@ static void gen_bounds_epilog(void) · 18 unmodified lines
700 if (offset_modified) {700 if (offset_modified) {
701 saved_ind = ind;701 saved_ind = ind;
702 ind = func_bound_ind;702 ind = func_bound_ind;
703 greloca(cur_text_section, sym_data, ind + 2, R_X86_64_64, 0);703 greloca(cur_text_section, sym_data, ind + 3, R_X86_64_PC32, -4);
704 ind = ind + 10;704 ind = ind + 7;
705 gen_bounds_call(TOK___bound_local_new);705 gen_bounds_call(TOK___bound_local_new);
706 ind = saved_ind;706 ind = saved_ind;
707 }707 }
708 708
709 /* generate bound check local freeing */709 /* generate bound check local freeing */
710 o(0x5250); /* save returned value, if any */710 o(0x5250); /* save returned value, if any */
711 greloca(cur_text_section, sym_data, ind + 2, R_X86_64_64, 0);711 greloca(cur_text_section, sym_data, ind + 3, R_X86_64_PC32, -4);
712 o(0xb848 + TREG_FASTCALL_1 * 0x100); /* mov xxx, %rcx/di */712 o(0x0d8d48 + ((TREG_FASTCALL_1 == TREG_RDI) * 0x300000)); /* lea xxx(%rip), %rcx/rdi */
713 gen_le64 (0);713 gen_le32 (0);
714 gen_bounds_call(TOK___bound_local_delete);714 gen_bounds_call(TOK___bound_local_delete);
715 o(0x585a); /* restore returned value, if any */715 o(0x585a); /* restore returned value, if any */
716}716}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t