@@ -204,8 +204,28 @@ fn compile_probe(
204204
205205 let sema_name = format_ident ! ( "__usdt_sema_{}_{}" , provider. name, probe. name) ;
206206 let options = if cfg ! ( target_arch = "x86_64" ) || cfg ! ( target_arch = "x86" ) {
207- // Use att_syntax on x86 to generate GNU Assembly Syntax for the
208- // registers automatically.
207+ // STAPSDT probes contain an "arguments" string which contains the
208+ // size, type, and location of each argument. This string is expected
209+ // to be in the AT&T syntax: we change the syntax for x86 only, as only
210+ // there the syntax effects register naming. The rest of our inline
211+ // assembly here is the same in both AT&T and Intel syntax, so we can
212+ // freely change the syntax without changing the generating code.
213+ // The arguments string on x86 looks like this:
214+ // * "2@%ax -4@%edi 8f@%rsi"
215+ // and in our inline assembly it is as follows:
216+ // * "2@{arg0} -4@{arg1} 8f@{arg2}"
217+ // The argument size and type is explicitly named on the left side of
218+ // the "@" sign, but the register is given by argument name instead of
219+ // explicitly naming eg. "%ax". This gives the compiler the freedom to
220+ // choose for itself where it wants to place the arguments. The only
221+ // thing we need to make sure of is that the argument register strings
222+ // are in the AT&T syntax: in Intel syntax the the "%" character would
223+ // be missing from the register names.
224+ // Note that we could manually fill in the "%" character and still use
225+ // Intel syntax, but that will break down if Rust's inline assembly
226+ // ever gets memory operands. Memory operands in the syntax look like:
227+ // * "8@0x18(%rsp)"
228+ // for "8-byte unsigned integer at stack + 0x18".
209229 quote ! { options( att_syntax, nomem, nostack, preserves_flags) }
210230 } else {
211231 quote ! { options( nomem, nostack, preserves_flags) }
0 commit comments