1
0
mirror of https://github.com/golang/go synced 2024-11-07 09:46:12 -07:00

cmd/link: store COFF symbol complex type in the LSB instead of the MSB

Microsoft's PE documentation is contradictory. It says that the
symbol's complex type [1] is stored in the pesym.Type most significant
byte (MSB), but MSVC, LLVM, and mingw store it in the 4 high bits of
the less significant byte (LSB). dumpbin understands both encoding.

Previous to CL 475355 the Go compiler mixed MSB and LSB encoding.
CL 475355 updated to compiler to use the MSB, but this causes problems
with mingw, which emits a warning when MSB is used.

For reference, LLVM also hit this issue long time ago:
https://github.com/llvm/llvm-project/issues/8692

[1] https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#type-representation

Change-Id: I7e750bde9c20e2c4c1c023203d7abd6fb26d9d30
Reviewed-on: https://go-review.googlesource.com/c/go/+/475855
Reviewed-by: Bryan Mills <bcmills@google.com>
Run-TryBot: Quim Muntal <quimmuntal@gmail.com>
Reviewed-by: Than McIntosh <thanm@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Ian Lance Taylor <iant@google.com>
This commit is contained in:
qmuntal 2023-03-13 14:34:38 +01:00 committed by Quim Muntal
parent a54fe8a270
commit b37c0602cd
2 changed files with 14 additions and 5 deletions

View File

@ -753,13 +753,19 @@ func (f *peFile) writeSymbols(ctxt *Link) {
if ctxt.IsExternal() {
peSymType = IMAGE_SYM_TYPE_NULL
} else {
peSymType = IMAGE_SYM_DTYPE_ARRAY<<8 + IMAGE_SYM_TYPE_STRUCT
// Microsoft's PE documentation is contradictory. It says that the symbol's complex type
// is stored in the pesym.Type most significant byte, but MSVC, LLVM, and mingw store it
// in the 4 high bits of the less significant byte.
peSymType = IMAGE_SYM_DTYPE_ARRAY<<4 + IMAGE_SYM_TYPE_STRUCT
}
sect, value, err := f.mapToPESection(ldr, s, ctxt.LinkMode)
if err != nil {
if t == sym.SDYNIMPORT || t == sym.SHOSTOBJ || t == sym.SUNDEFEXT {
peSymType = IMAGE_SYM_DTYPE_FUNCTION << 8
} else {
switch t {
case sym.SDYNIMPORT, sym.SHOSTOBJ, sym.SUNDEFEXT:
// Microsoft's PE documentation says that the basic type for a function should be
// IMAGE_SYM_TYPE_VOID, but the reality is that it uses IMAGE_SYM_TYPE_NULL instead.
peSymType = IMAGE_SYM_DTYPE_FUNCTION<<4 + IMAGE_SYM_TYPE_NULL
default:
ctxt.Errorf(s, "addpesym: %v", err)
}
}

View File

@ -672,7 +672,10 @@ func (state *peLoaderState) readpesym(pesym *pe.COFFSymbol) (*loader.SymbolBuild
var s loader.Sym
var bld *loader.SymbolBuilder
switch uint8(pesym.Type >> 8) {
// Microsoft's PE documentation is contradictory. It says that the symbol's complex type
// is stored in the pesym.Type most significant byte, but MSVC, LLVM, and mingw store it
// in the 4 high bits of the less significant byte.
switch uint8(pesym.Type&0xf0) >> 4 {
default:
return nil, 0, fmt.Errorf("%s: invalid symbol type %d", symname, pesym.Type)