diff --git a/gas/ChangeLog b/gas/ChangeLog index cbe2a57dfee..9f966be40b5 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,15 @@ +2023-11-18 Jose E. Marchesi + + * config/tc-bpf.c (parse_bpf_register): Move before + bpf_parse_name. + (bpf_parse_name): Do not allow using symbols that are also + register names as operands in pseudo-c syntax. + * testsuite/gas/bpf/regs-for-symbols-pseudoc.d: New file. + * testsuite/gas/bpf/regs-for-symbols-pseudoc.s: Likewise. + * testsuite/gas/bpf/regs-for-symbols-pseudoc.l: Likewise. + * doc/c-bpf.texi (BPF Registers): Document that it is not possible + to refer to register names as symbols in instruction operands. + 2023-11-15 YunQiang Su * testsuite/gas/mips/mips.exp (mips_arch_create): Add "--defsym diff --git a/gas/config/tc-bpf.c b/gas/config/tc-bpf.c index 3122f80804a..45abc3c9578 100644 --- a/gas/config/tc-bpf.c +++ b/gas/config/tc-bpf.c @@ -1255,71 +1255,6 @@ parse_expression (char *s, expressionS *exp) return s; } -/* Symbols created by this parse, but not yet committed to the real - symbol table. */ -static symbolS *deferred_sym_rootP; -static symbolS *deferred_sym_lastP; - -/* Symbols discarded by a previous parse. Symbols cannot easily be freed - after creation, so try to recycle. */ -static symbolS *orphan_sym_rootP; -static symbolS *orphan_sym_lastP; - -/* Implement md_parse_name hook. Handles any symbol found in an expression. - This allows us to tentatively create symbols, before we know for sure - whether the parser is using the correct template for an instruction. - If we end up keeping the instruction, the deferred symbols are committed - to the real symbol table. This approach is modeled after the riscv port. */ - -bool -bpf_parse_name (const char *name, expressionS *exp, enum expr_mode mode) -{ - symbolS *sym; - - /* If we aren't currently parsing an instruction, don't do anything. - This prevents tampering with operands to directives. */ - if (!parsing_insn_operands) - return false; - - gas_assert (mode == expr_normal); - - if (symbol_find (name) != NULL) - return false; - - for (sym = deferred_sym_rootP; sym; sym = symbol_next (sym)) - if (strcmp (name, S_GET_NAME (sym)) == 0) - break; - - /* Tentatively create a symbol. */ - if (!sym) - { - /* See if we can reuse a symbol discarded by a previous parse. - This may be quite common, for example when trying multiple templates - for an instruction with the first reference to a valid symbol. */ - for (sym = orphan_sym_rootP; sym; sym = symbol_next (sym)) - if (strcmp (name, S_GET_NAME (sym)) == 0) - { - symbol_remove (sym, &orphan_sym_rootP, &orphan_sym_lastP); - break; - } - - if (!sym) - sym = symbol_create (name, undefined_section, &zero_address_frag, 0); - - /* Add symbol to the deferred list. If we commit to the isntruction, - then the symbol will be inserted into to the real symbol table at - that point (in md_assemble). */ - symbol_append (sym, deferred_sym_lastP, &deferred_sym_rootP, - &deferred_sym_lastP); - } - - exp->X_op = O_symbol; - exp->X_add_symbol = sym; - exp->X_add_number = 0; - - return true; -} - /* Parse a BPF register name and return the corresponding register number. Return NULL in case of parse error, or a pointer to the first character in S that is not part of the register name. */ @@ -1368,6 +1303,88 @@ parse_bpf_register (char *s, char rw, uint8_t *regno) return s; } +/* Symbols created by this parse, but not yet committed to the real + symbol table. */ +static symbolS *deferred_sym_rootP; +static symbolS *deferred_sym_lastP; + +/* Symbols discarded by a previous parse. Symbols cannot easily be freed + after creation, so try to recycle. */ +static symbolS *orphan_sym_rootP; +static symbolS *orphan_sym_lastP; + +/* Implement md_parse_name hook. Handles any symbol found in an expression. + This allows us to tentatively create symbols, before we know for sure + whether the parser is using the correct template for an instruction. + If we end up keeping the instruction, the deferred symbols are committed + to the real symbol table. This approach is modeled after the riscv port. */ + +bool +bpf_parse_name (const char *name, expressionS *exp, enum expr_mode mode) +{ + symbolS *sym; + + /* If we aren't currently parsing an instruction, don't do anything. + This prevents tampering with operands to directives. */ + if (!parsing_insn_operands) + return false; + + gas_assert (mode == expr_normal); + + /* Pseudo-C syntax uses unprefixed register names like r2 or w3. + Since many instructions take either a register or an + immediate/expression, we should not allow references to symbols + with these names in operands. */ + if (asm_dialect == DIALECT_PSEUDOC) + { + uint8_t regno; + + if (parse_bpf_register ((char *) name, 'r', ®no) + || parse_bpf_register ((char *) name, 'w', ®no)) + { + as_bad (_("unexpected register name `%s' in expression"), + name); + return false; + } + } + + if (symbol_find (name) != NULL) + return false; + + for (sym = deferred_sym_rootP; sym; sym = symbol_next (sym)) + if (strcmp (name, S_GET_NAME (sym)) == 0) + break; + + /* Tentatively create a symbol. */ + if (!sym) + { + /* See if we can reuse a symbol discarded by a previous parse. + This may be quite common, for example when trying multiple templates + for an instruction with the first reference to a valid symbol. */ + for (sym = orphan_sym_rootP; sym; sym = symbol_next (sym)) + if (strcmp (name, S_GET_NAME (sym)) == 0) + { + symbol_remove (sym, &orphan_sym_rootP, &orphan_sym_lastP); + break; + } + + if (!sym) + sym = symbol_create (name, undefined_section, &zero_address_frag, 0); + + /* Add symbol to the deferred list. If we commit to the isntruction, + then the symbol will be inserted into to the real symbol table at + that point (in md_assemble). */ + symbol_append (sym, deferred_sym_lastP, &deferred_sym_rootP, + &deferred_sym_lastP); + } + + exp->X_op = O_symbol; + exp->X_add_symbol = sym; + exp->X_add_number = 0; + + return true; +} + /* Collect a parse error message. */ static int partial_match_length = 0; diff --git a/gas/doc/c-bpf.texi b/gas/doc/c-bpf.texi index bdd9fde0f5a..25ae231d19c 100644 --- a/gas/doc/c-bpf.texi +++ b/gas/doc/c-bpf.texi @@ -113,7 +113,12 @@ Read-only frame pointer register. @noindent Note that in the Pseudo-C syntax register names are not preceded by -@code{%} characters. +@code{%} characters. A consequence of that is that in contexts like +instruction operands, where both register names and expressions +involving symbols are expected, there is no way to disambiguate +between them. In order to keep things simple, this assembler does not +allow to refer to symbols whose names collide with register names in +instruction operands. @node BPF Directives @section BPF Directives diff --git a/gas/testsuite/gas/bpf/bpf.exp b/gas/testsuite/gas/bpf/bpf.exp index fcbeccd8ecd..5bcd8c483a0 100644 --- a/gas/testsuite/gas/bpf/bpf.exp +++ b/gas/testsuite/gas/bpf/bpf.exp @@ -73,6 +73,10 @@ if {[istarget bpf*-*-*]} { run_dump_test disp32-overflow run_dump_test imm32-overflow + # In Pseudo-C it is not possible to refer to symbols + # as operands that have the same name than registers. + run_dump_test regs-for-symbols-pseudoc + # Test that parser does not create undefined symbols run_dump_test asm-extra-sym-1 } diff --git a/gas/testsuite/gas/bpf/regs-for-symbols-pseudoc.d b/gas/testsuite/gas/bpf/regs-for-symbols-pseudoc.d new file mode 100644 index 00000000000..d99ec8f94c2 --- /dev/null +++ b/gas/testsuite/gas/bpf/regs-for-symbols-pseudoc.d @@ -0,0 +1,3 @@ +#as: -EL -mdialect=pseudoc +#source: regs-for-symbols-pseudoc.s +#error_output: regs-for-symbols-pseudoc.l diff --git a/gas/testsuite/gas/bpf/regs-for-symbols-pseudoc.l b/gas/testsuite/gas/bpf/regs-for-symbols-pseudoc.l new file mode 100644 index 00000000000..eeda735fb99 --- /dev/null +++ b/gas/testsuite/gas/bpf/regs-for-symbols-pseudoc.l @@ -0,0 +1,8 @@ +.*: Assembler messages: +.*:1: Error: unexpected register name `w3' in expression +.*:2: Error: unexpected register name `r3' in expression +.*:2: Error: unexpected register name `r3' in expression +.*:3: Error: unexpected register name `r3' in expression +.*:3: Error: unexpected register name `r3' in expression +.*:4: Error: unexpected register name `r3' in expression +.*:4: Error: unexpected register name `r3' in expression diff --git a/gas/testsuite/gas/bpf/regs-for-symbols-pseudoc.s b/gas/testsuite/gas/bpf/regs-for-symbols-pseudoc.s new file mode 100644 index 00000000000..693787d5479 --- /dev/null +++ b/gas/testsuite/gas/bpf/regs-for-symbols-pseudoc.s @@ -0,0 +1,4 @@ + goto w3 + r2 = r3 ll + r2 = r3+1 ll + r2 = 1+r3 ll