History

tccasm: Support refs to anon symbols from asm

This happens when e.g. string constants (or other static data) are passed as operands to inline asm as immediates. The produced symbol ref wouldn't be found. So tighten the connection between C and asm-local symbol table even more.

Michael Matz committed 10 years ago

Commit 5bd8aeb1 parent dd57a344 files · +52 −13Browse files

Unified · Split

4 files
  1. i386-asm.c +11 −2
  2. tcc.h +1 −0
  3. tccasm.c +17 −11
  4. tests/tcctest.c +23 −0
i386-asm.c+11−2
@@ -1437,10 +1437,19 @@ ST_FUNC void subst_asm_operand(CString *add_str, · 1436 unmodified lines
1437 modifier != 'P')1437 modifier != 'P')
1438 cstr_ccat(add_str, '$');1438 cstr_ccat(add_str, '$');
1439 if (r & VT_SYM) {1439 if (r & VT_SYM) {
1440 cstr_cat(add_str, get_tok_str(sv->sym->v, NULL), -1);1440 const char *name = get_tok_str(sv->sym->v, NULL);
1441 if (sv->sym->v >= SYM_FIRST_ANOM) {
1442 /* In case of anonymuous symbols ("L.42", used
1443 for static data labels) we can't find them
1444 in the C symbol table when later looking up
1445 this name. So enter them now into the asm label
1446 list when we still know the symbol. */
1447 get_asm_sym(tok_alloc(name, strlen(name))->tok, sv->sym);
1448 }
1449 cstr_cat(add_str, name, -1);
1441 if ((uint32_t)sv->c.i == 0)1450 if ((uint32_t)sv->c.i == 0)
1442 goto no_offset;1451 goto no_offset;
1443 cstr_ccat(add_str, '+');1452 cstr_ccat(add_str, '+');
1444 }1453 }
1445 val = sv->c.i;1454 val = sv->c.i;
1446 if (modifier == 'n')1455 if (modifier == 'n')
tcc.h+1−0
@@ -1529,6 +1529,7 @@ ST_FUNC void asm_instr(void); · 1528 unmodified lines
1529ST_FUNC void asm_global_instr(void);1529ST_FUNC void asm_global_instr(void);
1530#ifdef CONFIG_TCC_ASM1530#ifdef CONFIG_TCC_ASM
1531ST_FUNC int find_constraint(ASMOperand *operands, int nb_operands, const char *name, const char **pp);1531ST_FUNC int find_constraint(ASMOperand *operands, int nb_operands, const char *name, const char **pp);
1532ST_FUNC Sym* get_asm_sym(int name, Sym *csym);
1532ST_FUNC void asm_expr(TCCState *s1, ExprValue *pe);1533ST_FUNC void asm_expr(TCCState *s1, ExprValue *pe);
1533ST_FUNC int asm_int_expr(TCCState *s1);1534ST_FUNC int asm_int_expr(TCCState *s1);
1534ST_FUNC int tcc_assemble(TCCState *s1, int do_preprocess);1535ST_FUNC int tcc_assemble(TCCState *s1, int do_preprocess);
tccasm.c+17−11
@@ -43,19 +43,24 @@ static Sym sym_dot; · 42 unmodified lines
43 43
44 This routine gives back either an existing asm-internal44 This routine gives back either an existing asm-internal
45 symbol, or a new one. In the latter case the new asm-internal45 symbol, or a new one. In the latter case the new asm-internal
46 symbol is initialized with info from the C symbol table. */46 symbol is initialized with info from the C symbol table.
47static Sym* get_asm_sym(int name)47
48 If CSYM is non-null we take symbol info from it, otherwise
49 we look up NAME in the C symbol table and use that. */
50ST_FUNC Sym* get_asm_sym(int name, Sym *csym)
48{51{
49 Sym *sym = label_find(name);52 Sym *sym = label_find(name);
50 if (!sym) {53 if (!sym) {
51 Sym *csym = sym_find(name);
52 sym = label_push(&tcc_state->asm_labels, name, 0);54 sym = label_push(&tcc_state->asm_labels, name, 0);
53 sym->type.t = VT_VOID | VT_EXTERN;55 sym->type.t = VT_VOID | VT_EXTERN;
54 /* We might be called for an asm block from inside a C routine56 if (!csym) {
55 and so might have local decls on the identifier stack. Search57 csym = sym_find(name);
56 for the first global one. */58 /* We might be called for an asm block from inside a C routine
57 while (csym && csym->scope)59 and so might have local decls on the identifier stack. Search
58 csym = csym->prev_tok;60 for the first global one. */
61 while (csym && csym->scope)
62 csym = csym->prev_tok;
63 }
59 /* Now, if we have a defined global symbol copy over64 /* Now, if we have a defined global symbol copy over
60 section and offset. */65 section and offset. */
61 if (csym &&66 if (csym &&
@@ -63,6 +68,7 @@ static Sym* get_asm_sym(int name) · 1 unmodified line
63 csym->c) {68 csym->c) {
64 ElfW(Sym) *esym;69 ElfW(Sym) *esym;
65 esym = &((ElfW(Sym) *)symtab_section->data)[csym->c];70 esym = &((ElfW(Sym) *)symtab_section->data)[csym->c];
71 sym->c = csym->c;
66 sym->r = esym->st_shndx;72 sym->r = esym->st_shndx;
67 sym->jnext = esym->st_value;73 sym->jnext = esym->st_value;
68 /* XXX can't yet store st_size anywhere. */74 /* XXX can't yet store st_size anywhere. */
@@ -158,7 +164,7 @@ static void asm_expr_unary(TCCState *s1, ExprValue *pe) · 89 unmodified lines
158 default:164 default:
159 if (tok >= TOK_IDENT) {165 if (tok >= TOK_IDENT) {
160 /* label case : if the label was not found, add one */166 /* label case : if the label was not found, add one */
161 sym = get_asm_sym(tok);167 sym = get_asm_sym(tok, NULL);
162 if (sym->r == SHN_ABS) {168 if (sym->r == SHN_ABS) {
163 /* if absolute symbol, no need to put a symbol value */169 /* if absolute symbol, no need to put a symbol value */
164 pe->v = sym->jnext;170 pe->v = sym->jnext;
@@ -682,7 +688,7 @@ static void asm_parse_directive(TCCState *s1) · 517 unmodified lines
682 Sym *sym;688 Sym *sym;
683 689
684 next();690 next();
685 sym = get_asm_sym(tok);691 sym = get_asm_sym(tok, NULL);
686 if (tok1 != TOK_ASMDIR_hidden)692 if (tok1 != TOK_ASMDIR_hidden)
687 sym->type.t &= ~VT_STATIC;693 sym->type.t &= ~VT_STATIC;
688 if (tok1 == TOK_ASMDIR_weak)694 if (tok1 == TOK_ASMDIR_weak)
@@ -801,7 +807,7 @@ static void asm_parse_directive(TCCState *s1) · 112 unmodified lines
801 const char *newtype;807 const char *newtype;
802 808
803 next();809 next();
804 sym = get_asm_sym(tok);810 sym = get_asm_sym(tok, NULL);
805 next();811 next();
806 skip(',');812 skip(',');
807 if (tok == TOK_STR) {813 if (tok == TOK_STR) {
tests/tcctest.c+23−0
@@ -2741,6 +2741,28 @@ void override_func2 (void) · 2740 unmodified lines
2741 printf ("asmc: override2\n");2741 printf ("asmc: override2\n");
2742}2742}
2743 2743
2744/* This checks a construct used by the linux kernel to encode
2745 references to strings by PC relative references. */
2746extern int bug_table[] __attribute__((section("__bug_table")));
2747char * get_asm_string (void)
2748{
2749 extern int some_symbol;
2750 asm volatile (".globl some_symbol\n"
2751 "jmp .+6\n"
2752 "1:\n"
2753 "some_symbol: .long 0\n"
2754 ".pushsection __bug_table, \"a\"\n"
2755 ".globl bug_table\n"
2756 "bug_table:\n"
2757 /* The first entry (1b-2b) is unused in this test,
2758 but we include it to check if cross-section
2759 PC-relative references work. */
2760 "2:\t.long 1b - 2b, %c0 - 2b\n"
2761 ".popsection\n" : : "i" ("A string"));
2762 char * str = ((char*)bug_table) + bug_table[1];
2763 return str;
2764}
2765
2744unsigned int set;2766unsigned int set;
2745 2767
2746void asm_test(void)2768void asm_test(void)
@@ -2812,6 +2834,7 @@ void asm_test(void) · 65 unmodified lines
2812 if (!somebool)2834 if (!somebool)
2813 printf("asmbool: failed\n");2835 printf("asmbool: failed\n");
2814#endif2836#endif
2837 printf("asmstr: %s\n", get_asm_string());
2815 return;2838 return;
2816 label1:2839 label1:
2817 goto label2;2840 goto label2;

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