LLVM Bugzilla is read-only and represents the historical archive of all LLVM issues filled before November 26, 2021. Use github to submit LLVM bugs

Bug 34392 - llvm-nm yields incorrect result for Webassembly objects
Summary: llvm-nm yields incorrect result for Webassembly objects
Status: RESOLVED FIXED
Alias: None
Product: tools
Classification: Unclassified
Component: llvm-nm (show other bugs)
Version: 5.0
Hardware: PC Linux
: P normal
Assignee: Sam Clegg
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2017-08-30 21:21 PDT by Michael Vogelsang
Modified: 2017-09-08 10:24 PDT (History)
3 users (show)

See Also:
Fixed By Commit(s):


Attachments
test.c (71 bytes, text/x-csrc)
2017-08-30 21:21 PDT, Michael Vogelsang
Details
armtest.o (728 bytes, application/x-object)
2017-08-30 21:22 PDT, Michael Vogelsang
Details
wasmtest.o (429 bytes, application/x-object)
2017-08-30 21:23 PDT, Michael Vogelsang
Details
wasmtestdis.wast (1.25 KB, text/plain)
2017-08-30 21:23 PDT, Michael Vogelsang
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Michael Vogelsang 2017-08-30 21:21:56 PDT
Created attachment 19067 [details]
test.c

llvm-nm is able to process binary wasm object files and produce well-formatted results, but the results aren't sensible or useful. I'll outline the expected behaviour and actual behaviour.

If we have a file `test.c` with the contents
'''
char first[0xF];
char second[0xFF];
char third[0x9];
char fourth[0xA];
'''

and compile it to ARM using a clang that is set to target `aarch64-unknown-linux-gnu` with the command `$CC -c test.c -o armtest.o` we can look at the GNU nm output with `nm -P armtest.o` with the following results.
'''
$d.0 n 0000000000000000 
first C 000000000000000f 000000000000000f
fourth C 000000000000000a 000000000000000a
second C 00000000000000ff 00000000000000ff
third C 0000000000000009 0000000000000009
'''

llvm-nm yields a similar enough result with `llvm-nm -P armtest.o`
'''
$d.0 n 0 0
first C f 0
fourth C a 0
second C ff 0
third C 9 0
'''

Now, we can compile test.c to wasm using a clang set to target `wasm32-unknown-unknown-wasm` with the command `$CC -c test.c -o wasmtest.o`. GNU nm, of course, just errors if you try to run it on wasmtest.o. However `llvm-nm -P wasmtest.o` yields the following.
'''
first D 0 0
fourth D 3 0
second D 1 0
third D 2 0
'''

It kinda just spits out the symbols with a number that indicates the relative declaration order.
It is worthwhile to take a look at the wasm-dis of wasmtest.o.
'''
(module
 (global $global$0 i32 (i32.const 0))
 (global $global$1 i32 (i32.const 16))
 (global $global$2 i32 (i32.const 271))
 (global $global$3 i32 (i32.const 280))
 (table 0 anyfunc)
 (memory $0 1)
 (data (i32.const 0) "\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00\00")
 (export "first" (global $global$0))
 (export "second" (global $global$1))
 (export "third" (global $global$2))
 (export "fourth" (global $global$3))
 ;; custom section "linking", size 15
)
'''

Notice, lines 2-5 seem to indicate that the information necessary to determine symbol values/sizes and offsets is available in wasmtest.o, the file just isn't getting processed correctly. Somehow, for each symbol we're getting the 'x' out of it's '$global$x'. 

test.c, armtest.o, wasmtest.o, and the wasm-dis are attached. 

Sorry to preemptively ping you on this Derek. I couldn't file this under llvm-nm and something wasm related, so I figured I should at least tag someone on the wasm team to make you all aware. 

GHC's build system actually relies on using nm at one point. Our current workaround is to compile with -flto and parse the llvm-dis of the necessary object files.
Comment 1 Michael Vogelsang 2017-08-30 21:22:42 PDT
Created attachment 19068 [details]
armtest.o
Comment 2 Michael Vogelsang 2017-08-30 21:23:10 PDT
Created attachment 19069 [details]
wasmtest.o
Comment 3 Michael Vogelsang 2017-08-30 21:23:37 PDT
Created attachment 19070 [details]
wasmtestdis.wast
Comment 4 Derek Schuff 2017-08-31 09:26:22 PDT
@Michael: Thanks for the report! No problem on pinging me. I've CC'd Sam Clegg, who is doing most of the work on wasm object files.

I think there are a couple of things going on here; First; I agree that the address/value of the symbol appears to be just getting printed as the index of its corresponding wasm global, and instead the initializer of that global should be printed (that's a pointer to the C global in the linear memory). This also seems to apply to llvm-objdump.

As for the size, that brings up another issue, which IIRC is that we currently don't support common symbols very well (or at all?). nm and objdump both handle those differently (objdump prints the alignment rather than the size of common symbols; I'm not sure what nm does; in your ARM example it looks like it's just printing the size as the value too). Anyway, I agree that we should print the size where applicable, and if not match one of the existing platforms, at least do something more useful than what we have now.
Comment 5 Sam Clegg 2017-09-08 10:24:23 PDT
Fixed in https://reviews.llvm.org/rL312294