Skip to content

Commit 75a0b9d

Browse files
Clément Chigotianlancetaylor
authored andcommitted
cmd: add DWARF64 support for aix port
This commit adds support for DWARF 64bits which is needed for AIX operating system. It also adds the save of each compilation unit's size which will be used during XCOFF generation in a following patch. Updates: golang#25893 Change-Id: Icdd0a4dd02bc0a9f0df319c351fb1db944610015 Reviewed-on: https://go-review.googlesource.com/c/138729 Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Ian Lance Taylor <iant@golang.org>
1 parent bcc3447 commit 75a0b9d

File tree

3 files changed

+123
-25
lines changed

3 files changed

+123
-25
lines changed

src/cmd/internal/dwarf/dwarf.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ type Context interface {
179179
AddBytes(s Sym, b []byte)
180180
AddAddress(s Sym, t interface{}, ofs int64)
181181
AddSectionOffset(s Sym, size int, t interface{}, ofs int64)
182-
AddDWARFSectionOffset(s Sym, size int, t interface{}, ofs int64)
182+
AddDWARFAddrSectionOffset(s Sym, t interface{}, ofs int64)
183183
CurrentOffset(s Sym) int64
184184
RecordDclReference(from Sym, to Sym, dclIdx int, inlIndex int)
185185
RecordChildDieOffsets(s Sym, vars []*Var, offsets []int32)
@@ -895,7 +895,7 @@ func putattr(ctxt Context, s Sym, abbrev int, form int, cls int, value int64, da
895895

896896
case DW_FORM_data4: // constant, {line,loclist,mac,rangelist}ptr
897897
if cls == DW_CLS_PTR { // DW_AT_stmt_list and DW_AT_ranges
898-
ctxt.AddDWARFSectionOffset(s, 4, data, value)
898+
ctxt.AddDWARFAddrSectionOffset(s, data, value)
899899
break
900900
}
901901
ctxt.AddInt(s, 4, value)
@@ -932,7 +932,7 @@ func putattr(ctxt Context, s Sym, abbrev int, form int, cls int, value int64, da
932932
if data == nil {
933933
return fmt.Errorf("dwarf: null reference in %d", abbrev)
934934
}
935-
ctxt.AddDWARFSectionOffset(s, 4, data, value)
935+
ctxt.AddDWARFAddrSectionOffset(s, data, value)
936936

937937
case DW_FORM_ref1, // reference within the compilation unit
938938
DW_FORM_ref2, // reference

src/cmd/internal/obj/objfile.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -459,7 +459,12 @@ func (c dwCtxt) AddAddress(s dwarf.Sym, data interface{}, value int64) {
459459
func (c dwCtxt) AddSectionOffset(s dwarf.Sym, size int, t interface{}, ofs int64) {
460460
panic("should be used only in the linker")
461461
}
462-
func (c dwCtxt) AddDWARFSectionOffset(s dwarf.Sym, size int, t interface{}, ofs int64) {
462+
func (c dwCtxt) AddDWARFAddrSectionOffset(s dwarf.Sym, t interface{}, ofs int64) {
463+
size := 4
464+
if isDwarf64(c.Link) {
465+
size = 8
466+
}
467+
463468
ls := s.(*LSym)
464469
rsym := t.(*LSym)
465470
ls.WriteAddr(c.Link, ls.Size, size, rsym, ofs)
@@ -500,6 +505,10 @@ func (c dwCtxt) Logf(format string, args ...interface{}) {
500505
c.Link.Logf(format, args...)
501506
}
502507

508+
func isDwarf64(ctxt *Link) bool {
509+
return ctxt.Headtype == objabi.Haix
510+
}
511+
503512
func (ctxt *Link) dwarfSym(s *LSym) (dwarfInfoSym, dwarfLocSym, dwarfRangesSym, dwarfAbsFnSym, dwarfIsStmtSym *LSym) {
504513
if s.Type != objabi.STEXT {
505514
ctxt.Diag("dwarfSym of non-TEXT %v", s)

src/cmd/link/internal/ld/dwarf.go

Lines changed: 110 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,12 @@ func (c dwctxt) AddSectionOffset(s dwarf.Sym, size int, t interface{}, ofs int64
6767
r.Add = ofs
6868
}
6969

70-
func (c dwctxt) AddDWARFSectionOffset(s dwarf.Sym, size int, t interface{}, ofs int64) {
70+
func (c dwctxt) AddDWARFAddrSectionOffset(s dwarf.Sym, t interface{}, ofs int64) {
71+
size := 4
72+
if isDwarf64(c.linkctxt) {
73+
size = 8
74+
}
75+
7176
c.AddSectionOffset(s, size, t, ofs)
7277
ls := s.(*sym.Symbol)
7378
ls.R[len(ls.R)-1].Type = objabi.R_DWARFSECREF
@@ -95,6 +100,10 @@ func (c dwctxt) RecordChildDieOffsets(s dwarf.Sym, vars []*dwarf.Var, offsets []
95100
panic("should be used only in the compiler")
96101
}
97102

103+
func isDwarf64(ctxt *Link) bool {
104+
return ctxt.HeadType == objabi.Haix
105+
}
106+
98107
var gdbscript string
99108

100109
var dwarfp []*sym.Symbol
@@ -873,6 +882,33 @@ func defdwsymb(ctxt *Link, s *sym.Symbol, str string, t SymbolType, v int64, got
873882
}
874883
}
875884

885+
// createUnitLength creates the initial length field with value v and update
886+
// offset of unit_length if needed.
887+
func createUnitLength(ctxt *Link, s *sym.Symbol, v uint64) {
888+
if isDwarf64(ctxt) {
889+
s.AddUint32(ctxt.Arch, 0xFFFFFFFF)
890+
}
891+
addDwarfAddrField(ctxt, s, v)
892+
}
893+
894+
// addDwarfAddrField adds a DWARF field in DWARF 64bits or 32bits.
895+
func addDwarfAddrField(ctxt *Link, s *sym.Symbol, v uint64) {
896+
if isDwarf64(ctxt) {
897+
s.AddUint(ctxt.Arch, v)
898+
} else {
899+
s.AddUint32(ctxt.Arch, uint32(v))
900+
}
901+
}
902+
903+
// addDwarfAddrRef adds a DWARF pointer in DWARF 64bits or 32bits.
904+
func addDwarfAddrRef(ctxt *Link, s *sym.Symbol, t *sym.Symbol) {
905+
if isDwarf64(ctxt) {
906+
adddwarfref(ctxt, s, t, 8)
907+
} else {
908+
adddwarfref(ctxt, s, t, 4)
909+
}
910+
}
911+
876912
// compilationUnit is per-compilation unit (equivalently, per-package)
877913
// debug-related data.
878914
type compilationUnit struct {
@@ -1081,11 +1117,11 @@ func writelines(ctxt *Link, unit *compilationUnit, ls *sym.Symbol) {
10811117
// Write .debug_line Line Number Program Header (sec 6.2.4)
10821118
// Fields marked with (*) must be changed for 64-bit dwarf
10831119
unitLengthOffset := ls.Size
1084-
ls.AddUint32(ctxt.Arch, 0) // unit_length (*), filled in at end.
1120+
createUnitLength(ctxt, ls, 0) // unit_length (*), filled in at end
10851121
unitstart = ls.Size
10861122
ls.AddUint16(ctxt.Arch, 2) // dwarf version (appendix F) -- version 3 is incompatible w/ XCode 9.0's dsymutil, latest supported on OSX 10.12 as of 2018-05
10871123
headerLengthOffset := ls.Size
1088-
ls.AddUint32(ctxt.Arch, 0) // header_length (*), filled in at end.
1124+
addDwarfAddrField(ctxt, ls, 0) // header_length (*), filled in at end
10891125
headerstart = ls.Size
10901126

10911127
// cpos == unitstart + 4 + 2 + 4
@@ -1238,8 +1274,16 @@ func writelines(ctxt *Link, unit *compilationUnit, ls *sym.Symbol) {
12381274
dwarf.Uleb128put(dwarfctxt, ls, 1)
12391275
ls.AddUint8(dwarf.DW_LNE_end_sequence)
12401276

1241-
ls.SetUint32(ctxt.Arch, unitLengthOffset, uint32(ls.Size-unitstart))
1242-
ls.SetUint32(ctxt.Arch, headerLengthOffset, uint32(headerend-headerstart))
1277+
if ctxt.HeadType == objabi.Haix {
1278+
saveDwsectCUSize(".debug_line", unit.lib.String(), uint64(ls.Size-unitLengthOffset))
1279+
}
1280+
if isDwarf64(ctxt) {
1281+
ls.SetUint(ctxt.Arch, unitLengthOffset+4, uint64(ls.Size-unitstart)) // +4 because of 0xFFFFFFFF
1282+
ls.SetUint(ctxt.Arch, headerLengthOffset, uint64(headerend-headerstart))
1283+
} else {
1284+
ls.SetUint32(ctxt.Arch, unitLengthOffset, uint32(ls.Size-unitstart))
1285+
ls.SetUint32(ctxt.Arch, headerLengthOffset, uint32(headerend-headerstart))
1286+
}
12431287

12441288
// Apply any R_DWARFFILEREF relocations, since we now know the
12451289
// line table file indices for this compilation unit. Note that
@@ -1329,8 +1373,8 @@ func writeframes(ctxt *Link, syms []*sym.Symbol) []*sym.Symbol {
13291373
if haslinkregister(ctxt) {
13301374
cieReserve = 32
13311375
}
1332-
fs.AddUint32(ctxt.Arch, cieReserve) // initial length, must be multiple of thearch.ptrsize
1333-
fs.AddUint32(ctxt.Arch, 0xffffffff) // cid.
1376+
createUnitLength(ctxt, fs, uint64(cieReserve)) // initial length, must be multiple of thearch.ptrsize
1377+
addDwarfAddrField(ctxt, fs, 0xffffffff) // cid.
13341378
fs.AddUint8(3) // dwarf version (appendix F)
13351379
fs.AddUint8(0) // augmentation ""
13361380
dwarf.Uleb128put(dwarfctxt, fs, 1) // code_alignment_factor
@@ -1418,9 +1462,9 @@ func writeframes(ctxt *Link, syms []*sym.Symbol) []*sym.Symbol {
14181462
// ptrsize: address range
14191463
fs.AddUint32(ctxt.Arch, uint32(4+2*ctxt.Arch.PtrSize+len(deltaBuf))) // length (excludes itself)
14201464
if ctxt.LinkMode == LinkExternal {
1421-
adddwarfref(ctxt, fs, fs, 4)
1465+
addDwarfAddrRef(ctxt, fs, fs)
14221466
} else {
1423-
fs.AddUint32(ctxt.Arch, 0) // CIE offset
1467+
addDwarfAddrField(ctxt, fs, 0) // CIE offset
14241468
}
14251469
fs.AddAddr(ctxt.Arch, s)
14261470
fs.AddUintXX(ctxt.Arch, uint64(s.Size), ctxt.Arch.PtrSize) // address range
@@ -1455,11 +1499,11 @@ func writeinfo(ctxt *Link, syms []*sym.Symbol, units []*compilationUnit, abbrevs
14551499
// Write .debug_info Compilation Unit Header (sec 7.5.1)
14561500
// Fields marked with (*) must be changed for 64-bit dwarf
14571501
// This must match COMPUNITHEADERSIZE above.
1458-
s.AddUint32(ctxt.Arch, 0) // unit_length (*), will be filled in later.
1459-
s.AddUint16(ctxt.Arch, 4) // dwarf version (appendix F)
1502+
createUnitLength(ctxt, s, 0) // unit_length (*), will be filled in later.
1503+
s.AddUint16(ctxt.Arch, 4) // dwarf version (appendix F)
14601504

14611505
// debug_abbrev_offset (*)
1462-
adddwarfref(ctxt, s, abbrevsym, 4)
1506+
addDwarfAddrRef(ctxt, s, abbrevsym)
14631507

14641508
s.AddUint8(uint8(ctxt.Arch.PtrSize)) // address_size
14651509

@@ -1477,8 +1521,17 @@ func writeinfo(ctxt *Link, syms []*sym.Symbol, units []*compilationUnit, abbrevs
14771521
for _, child := range cu {
14781522
cusize += child.Size
14791523
}
1480-
cusize -= 4 // exclude the length field.
1481-
s.SetUint32(ctxt.Arch, 0, uint32(cusize))
1524+
// Save size for AIX symbol table.
1525+
if ctxt.HeadType == objabi.Haix {
1526+
saveDwsectCUSize(".debug_info", getPkgFromCUSym(s), uint64(cusize))
1527+
}
1528+
if isDwarf64(ctxt) {
1529+
cusize -= 12 // exclude the length field.
1530+
s.SetUint(ctxt.Arch, 4, uint64(cusize)) // 4 because of 0XFFFFFFFF
1531+
} else {
1532+
cusize -= 4 // exclude the length field.
1533+
s.SetUint32(ctxt.Arch, 0, uint32(cusize))
1534+
}
14821535
// Leave a breadcrumb for writepub. This does not
14831536
// appear in the DWARF output.
14841537
newattr(compunit, dwarf.DW_AT_byte_size, dwarf.DW_CLS_CONSTANT, cusize, 0)
@@ -1519,10 +1572,10 @@ func writepub(ctxt *Link, sname string, ispub func(*dwarf.DWDie) bool, syms []*s
15191572
culength := uint32(getattr(compunit, dwarf.DW_AT_byte_size).Value) + 4
15201573

15211574
// Write .debug_pubnames/types Header (sec 6.1.1)
1522-
s.AddUint32(ctxt.Arch, 0) // unit_length (*), will be filled in later.
1523-
s.AddUint16(ctxt.Arch, 2) // dwarf version (appendix F)
1524-
adddwarfref(ctxt, s, dtolsym(compunit.Sym), 4) // debug_info_offset (of the Comp unit Header)
1525-
s.AddUint32(ctxt.Arch, culength) // debug_info_length
1575+
createUnitLength(ctxt, s, 0) // unit_length (*), will be filled in later.
1576+
s.AddUint16(ctxt.Arch, 2) // dwarf version (appendix F)
1577+
addDwarfAddrRef(ctxt, s, dtolsym(compunit.Sym)) // debug_info_offset (of the Comp unit Header)
1578+
addDwarfAddrField(ctxt, s, uint64(culength)) // debug_info_length
15261579

15271580
for die := compunit.Child; die != nil; die = die.Link {
15281581
if !ispub(die) {
@@ -1533,19 +1586,31 @@ func writepub(ctxt *Link, sname string, ispub func(*dwarf.DWDie) bool, syms []*s
15331586
if die.Sym == nil {
15341587
fmt.Println("Missing sym for ", name)
15351588
}
1536-
adddwarfref(ctxt, s, dtolsym(die.Sym), 4)
1589+
addDwarfAddrRef(ctxt, s, dtolsym(die.Sym))
15371590
Addstring(s, name)
15381591
}
15391592

1540-
s.AddUint32(ctxt.Arch, 0)
1593+
addDwarfAddrField(ctxt, s, 0) // Null offset
15411594

1542-
s.SetUint32(ctxt.Arch, sectionstart, uint32(s.Size-sectionstart)-4) // exclude the length field.
1595+
// On AIX, save the current size of this compilation unit.
1596+
if ctxt.HeadType == objabi.Haix {
1597+
saveDwsectCUSize(sname, getPkgFromCUSym(dtolsym(compunit.Sym)), uint64(s.Size-sectionstart))
1598+
}
1599+
if isDwarf64(ctxt) {
1600+
s.SetUint(ctxt.Arch, sectionstart+4, uint64(s.Size-sectionstart)-12) // exclude the length field.
1601+
} else {
1602+
s.SetUint32(ctxt.Arch, sectionstart, uint32(s.Size-sectionstart)-4) // exclude the length field.
1603+
}
15431604
}
15441605

15451606
return syms
15461607
}
15471608

15481609
func writegdbscript(ctxt *Link, syms []*sym.Symbol) []*sym.Symbol {
1610+
// TODO (aix): make it available
1611+
if ctxt.HeadType == objabi.Haix {
1612+
return syms
1613+
}
15491614
if ctxt.LinkMode == LinkExternal && ctxt.HeadType == objabi.Hwindows && ctxt.BuildMode == BuildModeCArchive {
15501615
// gcc on Windows places .debug_gdb_scripts in the wrong location, which
15511616
// causes the program not to run. See https://golang.org/issue/20183
@@ -2019,3 +2084,27 @@ func (v compilationUnitByStartPC) Less(i, j int) bool {
20192084
return v[i].lib.Textp[0].Value < v[j].lib.Textp[0].Value
20202085
}
20212086
}
2087+
2088+
// On AIX, the symbol table needs to know where are the compilation units parts
2089+
// for a specific package in each .dw section.
2090+
// dwsectCUSize map will save the size of a compilation unit for
2091+
// the corresponding .dw section.
2092+
// This size can later be retrieved with the index "sectionName.pkgName".
2093+
var dwsectCUSize map[string]uint64
2094+
2095+
// getDwsectCUSize retrieves the corresponding package size inside the current section.
2096+
func getDwsectCUSize(sname string, pkgname string) uint64 {
2097+
return dwsectCUSize[sname+"."+pkgname]
2098+
}
2099+
2100+
func saveDwsectCUSize(sname string, pkgname string, size uint64) {
2101+
dwsectCUSize[sname+"."+pkgname] = size
2102+
}
2103+
2104+
// getPkgFromCUSym returns the package name for the compilation unit
2105+
// represented by s.
2106+
// The prefix dwarf.InfoPrefix+".pkg." needs to be removed in order to get
2107+
// the package name.
2108+
func getPkgFromCUSym(s *sym.Symbol) string {
2109+
return strings.TrimPrefix(s.Name, dwarf.InfoPrefix+".pkg.")
2110+
}

0 commit comments

Comments
 (0)