<html><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div class="">The issue is DW_OP_deref dereferences a pointer and pushes it onto the stack. The code currently, for a load address that is on top of the stack does:</div><div class=""><br class=""></div><div class=""><div style="margin: 0px; font-stretch: normal; line-height: normal; background-color: rgb(255, 255, 255);" class=""><span style="color: #3e8087" class="">Value</span>::<span style="color: #3e8087" class="">ValueType</span> value_type = stack.back().GetValueType();</div><div style="margin: 0px; font-stretch: normal; line-height: normal; background-color: rgb(255, 255, 255);" class=""><span style="color: #ad3da4" class=""><b class="">switch</b></span> (value_type) {</div></div><div class="">case Value::eValueTypeLoadAddress:<br class=""> if (exe_ctx) {<br class=""> if (process) {<br class=""> lldb::addr_t pointer_addr = stack.back().GetScalar().ULongLong(LLDB_INVALID_ADDRESS);<br class=""> Status error;<br class=""> lldb::addr_t pointer_value = process->ReadPointerFromMemory(pointer_addr, error);<br class=""> if (pointer_value != LLDB_INVALID_ADDRESS) {<br class=""> stack.back().GetScalar() = pointer_value;<br class=""> stack.back().ClearContext();<br class=""> } else {<br class=""> return false;<br class=""> }<br class=""><br class=""></div><div class="">Here we just use "stack.back()" to access the item at the top of the expression value stack. The top value has a Value::ValueType of Value::eValueTypeLoadAddress. We don't reset this value to be Value::<span style="background-color: rgb(255, 255, 255);" class="">eValueTypeScalar, but we probably should and that will probably fix this issue. </span></div><div class=""><span style="background-color: rgb(255, 255, 255);" class=""><br class=""></span></div><div class=""><span style="background-color: rgb(255, 255, 255);" class="">DWARF5 finally added the ability to track what each value means on the expression stack. Prior to DWARF 5, we had no idea what each entry on the expression value stack was (file address, load address (Value::</span>eValueTypeLoadAddress)<span style="background-color: rgb(255, 255, 255);" class="">, plain value (Value::</span><span style="background-color: rgb(255, 255, 255);" class="">eValueTypeScalar). We have tracked this info for a while now, but the DWARF5 spec is much more specific on how things should be treated. From the spec:</span></div><div class=""><span style="background-color: rgb(255, 255, 255);" class=""><br class=""></span></div><div class=""><span style="background-color: rgb(255, 255, 255);" class=""><div class="">DW_OP_deref<br class=""><br class=""></div><div class="">The DW_OP_deref operation pops the top stack entry and treats it as an address. The popped value must have an integral type. The value retrieved from that address is pushed, and has the generic type. The size of the data retrieved from the dereferenced address is the size of an address on the target machine.</div><div class=""><br class=""></div><div class="">No the "The value retrieved from that address is pushed, and has the generic type." statement. In LLDB this means the value's ValueType should be set to Value::eValueTypeScalar.</div></span></div><div class=""><span style="background-color: rgb(255, 255, 255);" class=""><br class=""></span></div><div class=""><span style="background-color: rgb(255, 255, 255);" class="">So try modifying the code with </span>stack.back().SetValueType(Value::eValueTypeScalar) after the stack.back().ClearContext():</div><div class=""><span style="background-color: rgb(255, 255, 255);" class=""><br class=""></span></div><div class=""><span style="background-color: rgb(255, 255, 255);" class=""> if (pointer_value != LLDB_INVALID_ADDRESS) {<br class=""> stack.back().GetScalar() = pointer_value;<br class=""> stack.back().ClearContext();</span></div><div class=""><span style="background-color: rgb(255, 255, 255);" class=""> <b class="">stack.back().</b></span><b class=""><span style="background-color: rgb(255, 255, 255);" class="">SetValueType(Value::</span><span style="background-color: rgb(255, 255, 255);" class="">eValueTypeScalar);</span></b><span style="background-color: rgb(255, 255, 255);" class=""><br class=""></span><span style="background-color: rgb(255, 255, 255);" class=""> } else {<br class=""> return false;<br class=""> }<br class=""></span></div><div class=""><span style="background-color: rgb(255, 255, 255);" class=""><br class=""></span></div><div class=""><span style="background-color: rgb(255, 255, 255);" class="">That might fix things.</span></div><div class=""><span style="background-color: rgb(255, 255, 255);" class=""><br class=""></span></div><div class=""><span style="background-color: rgb(255, 255, 255);" class="">The way the expression ends up right now we end up with an expression stack saying that the value is a load address which means we must read the value from memory in order to find it. This would be the right thing to do if your location expression was:</span></div><div class=""><span style="background-color: rgb(255, 255, 255);" class=""><br class=""></span></div><div class=""><span style="background-color: rgb(255, 255, 255);" class="">0x000000da: TAG_variable [9]<br class=""> AT_location( fbreg -16 )<br class=""> AT_name( "x" )<br class=""> AT_decl_file(...)<br class=""> AT_decl_line( 4 )<br class=""> AT_type( {0x00000204} ( $sxD ) )<br class=""></span></div><div class=""><span style="background-color: rgb(255, 255, 255);" class=""><br class=""></span></div><div class=""><span style="background-color: rgb(255, 255, 255);" class="">Note I removed the "deref" from the location expression. In this case the variable would need to be read from memory. If the value was to be in a register, then the location would be:</span></div><div class=""><span style="background-color: rgb(255, 255, 255);" class=""><br class=""></span></div><div class=""><span style="background-color: rgb(255, 255, 255);" class="">0x000000da: TAG_variable [9]<br class=""> AT_location( reg16 )<br class=""> AT_name( "x" )<br class=""> AT_decl_file(...)<br class=""> AT_decl_line( 4 )<br class=""> AT_type( {0x00000204} ( $sxD ) )<br class=""><br class=""></span></div><div class=""><span style="background-color: rgb(255, 255, 255);" class="">Then the value would be in register 16 itself (not dereferenced).</span></div><div class=""><span style="background-color: rgb(255, 255, 255);" class=""><br class=""></span></div><div class=""><span style="background-color: rgb(255, 255, 255);" class="">Hope this all makes sense. If you have any questions let me know.</span></div><div class=""><span style="background-color: rgb(255, 255, 255);" class=""><br class=""></span></div><div class=""><span style="background-color: rgb(255, 255, 255);" class="">Greg</span></div><div class=""><span style="background-color: rgb(255, 255, 255);" class=""><br class=""></span></div><div class=""><div><br class=""><blockquote type="cite" class=""><div class="">On Oct 11, 2018, at 10:52 AM, Davide Italiano <<a href="mailto:dccitaliano@gmail.com" class="">dccitaliano@gmail.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="">Hi Greg,<br class="">I have this issue that I suspect is a bug in lldb’s handling of DW_OP_deref.<br class="">I wasn’t able to craft an easy C++ testcase, so I’ll start from my<br class="">motivating (swift) example.<br class=""><br class="">Given the following code:<br class=""><br class="">func use<T>(_ t : T) {}<br class="">func single<T>(_ t : T) {<br class=""> let x = t<br class=""> use(x)<br class="">}<br class="">let s = "hello"<br class="">single(s)<br class=""><br class="">The IR emitted for the local binding `x` in `single<T>` is an alloca<br class="">containing the address of `x`. Hence, the DWARF, correctly contains a<br class="">DW_OP_deref expression, i.e.:<br class=""><br class="">0x000000da: TAG_variable [9]<br class=""> AT_location( fbreg -16, deref )<br class=""> AT_name( "x" )<br class=""> AT_decl_file(<br class="">"/Users/dcci/work/swift/build/Ninja-RelWithDebInfoAssert+stdlib-RelWithDebInfo/swift-macosx-x86_64/bin/pat.swift"<br class="">)<br class=""> AT_decl_line( 4 )<br class=""> AT_type( {0x00000204} ( $sxD ) )<br class=""><br class="">When I debug this with lldb, I expect lldb to print the value that’s<br class="">pointed by %rbp - 16,<br class="">i.e.<br class="">(lldb) register read $rbp<br class=""> rbp = 0x00007ffeefbff860<br class=""><br class="">(lldb) mem read 0x00007ffeefbff850<br class="">0x7ffeefbff850: 10 f8 bf ef fe 7f 00 00 b8 32 4d 00 01 00 00 00<br class="">.????...?2M.....<br class="">0x7ffeefbff860: c0 f8 bf ef fe 7f 00 00 64 09 00 00 01 00 00 00<br class="">?????...d.......<br class=""><br class="">So, the value that I expected to be printed is 0x7ffeefbff810.<br class=""><br class="">What I instead see in the debugger is:<br class="">(T) x = <read memory from 0xe500000000000000 failed (0 of 16 bytes read)><br class=""><br class="">The value `0xe500000000000000` happens to be the value that’s pointed<br class="">by the address 0x7ffeefbff810, that is:<br class=""><br class="">(lldb) mem read 0x7ffeefbff810<br class="">0x7ffeefbff810: 00 00 00 00 00 00 00 e5 68 65 6c 6c 6f 00 00 00<br class="">.......?hello...<br class="">0x7ffeefbff820: 05 00 00 00 00 00 00 00 40 32 4d 00 01 00 00 00<br class="">........@2M.....<br class=""><br class="">Is this an expected behavior? I did expect DW_OP_deref to just do a<br class="">single dereference and not two. It looks like when we call<br class="">`UpdateValue()` in lldb we do have the correct value in `m_value`, but<br class="">GetPointerValue() ends up printing the value that’s *pointed by*<br class="">what’s in `m_value`, i.e.<br class=""><br class=""> m_integer = {<br class=""> U = {<br class=""> VAL = 0x00007ffeefbff810<br class=""> pVal = 0x00007ffeefbff810<br class=""> }<br class=""><br class="">as this is a LoadAddress. Greg, as you wrote this code (and touched it<br class="">last), what do you expect to be the correct semantic here?<br class=""><br class="">Removing a dereference from DW_OP_deref in the DWARFASTParser works<br class="">around the issue, but I’m fairly sure it’s the incorrect fix. Are we<br class="">maybe setting the value type incorrectly?<br class=""><br class=""><br class="">Best,<br class=""><br class=""><br class="">—<br class=""><br class="">Davide<br class=""></div></div></blockquote></div><br class=""></div></body></html>