📄 structs.exp
字号:
} # Check that the return-value is as expected. At this stage we're # just checking that GDB has returned a value consistent with # "return_value_known" set above. # # Note that, when return_value_known is false, we can't make any # assumptions at all about the value L<n>: # # - If the caller passed the address of L<n> directly as fun<n>'s # return value buffer, then L<n> will be unchanged, because we # forced fun<n> to return before it could store anything in it. # # - If the caller passed the address of some temporary buffer to # fun<n>, and then copied the buffer into L<n>, then L<n> will # have been overwritten with whatever garbage was in the # uninitialized buffer. # # - However, if the temporary buffer just happened to have the # "right" value of foo<n> in it, then L<n> will, in fact, have # the value you'd expect to see if the 'return' had worked! # This has actually been observed to happen on the Renesas M32C. # # So, really, anything is acceptable unless return_value_known is # true. set test "value foo<n> returned; ${tests}" gdb_test_multiple "p/c L${n}" "${test}" { -re " = [foo ${n}].*${gdb_prompt} $" { # This answer is okay regardless of whether GDB claims to # have set the return value: if it did, then this is what # we expected; and if it didn't, then any answer is okay. pass "${test}" } -re " = [any $n].*${gdb_prompt} $" { if $return_value_known { # This contradicts the above claim that GDB knew # the location of the return value. fail "${test}" } else { # We expected L${n} to be set to garbage, so any # answer is acceptable. pass "${test}" } } -re ".*${gdb_prompt} $" { if $return_value_unimplemented { # What a suprize. The architecture hasn't implemented # return_value, and hence has to fail. kfail "$test" gdb/1444 } else { fail "$test" } } } # Check that a "finish" works. # This is almost but not quite the same as "call struct funcs". # Architectures can have subtle differences in the two code paths. # The relevant code snippet is "L{n} = fun{n}()". The program is # advanced into a call to "fun{n}" and then that function is # finished. The returned value that GDB prints, reformatted using # "p/c", is checked. # Get into "fun${n}()". gdb_test "advance fun${n}" \ "fun${n} .*\[\r\n\]+\[0-9\].*return foo${n}.*" \ "advance to fun<n> for finish; ${tests}" # Check that the program invalidated the relevant global. gdb_test "p/c L${n}" " = [zed $n]" "zed L<n> for finish; ${tests}" # Finish the function, set 'finish_value_known" to non-empty if # the return-value was found. set test "finish foo<n>; ${tests}" set finish_value_known 1 gdb_test_multiple "finish" "${test}" { -re "Value returned is .*${gdb_prompt} $" { pass "${test}" } -re "Cannot determine contents.*${gdb_prompt} $" { # Expected bad value. For the moment this is ok. set finish_value_known 0 pass "${test}" } } # Re-print the last (return-value) using the more robust # "p/c". If no return value was found, the 'Z' from the previous # check that the variable was cleared, is printed. set test "value foo<n> finished; ${tests}" gdb_test_multiple "p/c" "${test}" { -re "[foo ${n}]\[\r\n\]+${gdb_prompt} $" { if $finish_value_known { pass "${test}" } else { # This contradicts the above claim that GDB didn't # know the location of the return-value. fail "${test}" } } -re "[zed ${n}]\[\r\n\]+${gdb_prompt} $" { # The value didn't get found. This is "expected". if $finish_value_known { # This contradicts the above claim that GDB did # know the location of the return-value. fail "${test}" } else { pass "${test}" } } } # Finally, check that "return" and finish" have consistent # behavior. # Since "finish" works in more cases than "return" (see # RETURN_VALUE_ABI_RETURNS_ADDRESS and # RETURN_VALUE_ABI_PRESERVES_ADDRESS), the "return" value being # known implies that the "finish" value is known (but not the # reverse). set test "return value known implies finish value known; ${tests}" if {$return_value_known && ! $finish_value_known} { kfail gdb/1444 "${test}" } else { pass "${test}" }}# ABIs pass anything >8 or >16 bytes in memory but below that things# randomly use register and/and structure conventions. Check all# possible sized char structs in that range. But only a restricted# range of the other types.# NetBSD/PPC returns "unnatural" (3, 5, 6, 7) sized structs in memory.# d10v is weird. 5/6 byte structs go in memory. 2 or more char# structs go in memory. Everything else is in a register!# Test every single char struct from 1..17 in size. This is what the# original "structs" test was doing.start_structs_test { tc }test_struct_calls 1test_struct_calls 2test_struct_calls 3test_struct_calls 4test_struct_calls 5test_struct_calls 6test_struct_calls 7test_struct_calls 8test_struct_calls 9test_struct_calls 10test_struct_calls 11test_struct_calls 12test_struct_calls 13test_struct_calls 14test_struct_calls 15test_struct_calls 16test_struct_calls 17test_struct_returns 1test_struct_returns 2test_struct_returns 3test_struct_returns 4test_struct_returns 5test_struct_returns 6test_struct_returns 7test_struct_returns 8# Let the fun begin.# Assuming that any integer struct larger than 8 bytes goes in memory,# come up with many and varied combinations of a return struct. For# "struct calls" test just beyond that 8 byte boundary, for "struct# returns" test up to that boundary.# For floats, assumed that up to two struct elements can be stored in# floating point registers, regardless of their size.# The approx size of each structure it is computed assumed that tc=1,# ts=2, ti=4, tl=4, tll=8, tf=4, td=8, tld=16, and that all fields are# naturally aligned. Padding being added where needed. Note that# these numbers are just approx, the d10v has ti=2, a 64-bit has has# tl=8.# Approx size: 2, 4, ...start_structs_test { ts }test_struct_calls 1test_struct_calls 2test_struct_calls 3test_struct_calls 4test_struct_calls 5test_struct_returns 1test_struct_returns 2test_struct_returns 3test_struct_returns 4# Approx size: 4, 8, ...start_structs_test { ti }test_struct_calls 1test_struct_calls 2test_struct_calls 3test_struct_returns 1test_struct_returns 2# Approx size: 4, 8, ...start_structs_test { tl }test_struct_calls 1test_struct_calls 2test_struct_calls 3test_struct_returns 1test_struct_returns 2# Approx size: 8, 16, ...start_structs_test { tll }test_struct_calls 1test_struct_calls 2test_struct_returns 1# Approx size: 4, 8, ...start_structs_test { tf }test_struct_calls 1test_struct_calls 2test_struct_calls 3test_struct_returns 1test_struct_returns 2# Approx size: 8, 16, ...start_structs_test { td }test_struct_calls 1test_struct_calls 2test_struct_returns 1# Approx size: 16, 32, ...start_structs_test { tld }test_struct_calls 1test_struct_calls 2test_struct_returns 1# Approx size: 2+1=3, 4, ...start_structs_test { ts tc }test_struct_calls 2test_struct_calls 3test_struct_calls 4test_struct_calls 5test_struct_calls 6test_struct_calls 7test_struct_calls 8test_struct_returns 2# Approx size: 4+1=5, 6, ...start_structs_test { ti tc }test_struct_calls 2test_struct_calls 3test_struct_calls 4test_struct_calls 5test_struct_calls 6test_struct_returns 2# Approx size: 4+1=5, 6, ...start_structs_test { tl tc }test_struct_calls 2test_struct_calls 3test_struct_calls 4test_struct_calls 5test_struct_calls 6test_struct_returns 2# Approx size: 8+1=9, 10, ...start_structs_test { tll tc }test_struct_calls 2# Approx size: 4+1=5, 6, ...start_structs_test { tf tc }test_struct_calls 2test_struct_calls 3test_struct_calls 4test_struct_calls 5test_struct_calls 6test_struct_returns 2# Approx size: 8+1=9, 10, ...start_structs_test { td tc }test_struct_calls 2# Approx size: 16+1=17, 18, ...start_structs_test { tld tc }test_struct_calls 2# Approx size: (1+1)+2=4, 6, ...start_structs_test { tc ts }test_struct_calls 2test_struct_calls 3test_struct_calls 4test_struct_calls 5test_struct_calls 6test_struct_returns 2# Approx size: (1+3)+4=8, 12, ...start_structs_test { tc ti }test_struct_calls 2test_struct_calls 3test_struct_calls 4test_struct_returns 2# Approx size: (1+3)+4=8, 12, ...start_structs_test { tc tl }test_struct_calls 2test_struct_calls 3test_struct_calls 4test_struct_returns 2# Approx size: (1+7)+8=16, 24, ...start_structs_test { tc tll }test_struct_calls 2# Approx size: (1+3)+4=8, 12, ...start_structs_test { tc tf }test_struct_calls 2test_struct_calls 3test_struct_calls 4# Approx size: (1+7)+8=16, 24, ...start_structs_test { tc td }test_struct_calls 2# Approx size: (1+15)+16=32, 48, ...start_structs_test { tc tld }test_struct_calls 2# Some float combinations# Approx size: 8+4=12, 16, ...# d10v: 4+4=8, 12, ...start_structs_test { td tf }test_struct_calls 2test_struct_returns 2# Approx size: (4+4)+8=16, 32, ...# d10v: 4+4=8, 12, ...start_structs_test { tf td }test_struct_calls 2test_struct_returns 2return 0
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -