Skip to content

Commit 536b2d2

Browse files
authored
Merge pull request #11 from pipehuffer/master
OELF: fixes for C++/Zig generated binaries
2 parents 251c739 + 4ae2600 commit 536b2d2

3 files changed

Lines changed: 48 additions & 21 deletions

File tree

pkg/oelf/OELFGenDynlibData.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,11 @@ func (orbisElf *OrbisElf) GenerateLibrarySymbolDictionary(sdkPath string, libPat
153153
return err
154154
}
155155

156+
// convert absolute paths to library's file names
157+
for i := range libraries {
158+
libraries[i] = filepath.Base(libraries[i])
159+
}
160+
156161
// Swap libkernel with the first library to ensure it comes before anything else
157162
for i, library := range libraries {
158163
if library == "libkernel.so" {

pkg/oelf/OELFGenProgramHeaders.go

Lines changed: 43 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,54 @@ import (
66
"encoding/binary"
77
"math"
88
"sort"
9+
"strings"
910
)
1011

1112
type programHeaderList []*elf.Prog
1213

14+
func getFirstRwDataSection(e *elf.File) *elf.Section {
15+
for _, s := range e.Sections {
16+
if strings.HasPrefix(s.Name, ".data") && s.Name != ".data.rel.ro" {
17+
return s
18+
}
19+
}
20+
return nil
21+
}
22+
func getLastRwDataSection(e *elf.File) *elf.Section {
23+
for i := len(e.Sections) - 1; i >= 0; i-- {
24+
s := e.Sections[i]
25+
if strings.HasPrefix(s.Name, ".data") && s.Name != ".data.rel.ro" {
26+
return s
27+
}
28+
}
29+
return nil
30+
}
31+
1332
// GenerateProgramHeaders parses the input ELF's section header table to generate updated program headers.
1433
// Returns nil.
1534
func (orbisElf *OrbisElf) GenerateProgramHeaders() error {
1635
// Get all the necessary sections first
1736
// TODO: Verify these sections exist in OrbisElf.ValidateInputELF()
1837
textSection := orbisElf.ElfToConvert.Section(".text")
1938
relroSection := orbisElf.ElfToConvert.Section(".data.rel.ro")
20-
dataSection := orbisElf.ElfToConvert.Section(".data")
21-
bssSection := orbisElf.ElfToConvert.Section(".bss")
2239
procParamSection := orbisElf.ElfToConvert.Section(".data.sce_process_param")
40+
bssSection := orbisElf.ElfToConvert.Section(".bss")
2341

42+
firstDataSection := getFirstRwDataSection(orbisElf.ElfToConvert)
43+
lastDataSection := getLastRwDataSection(orbisElf.ElfToConvert)
44+
allDataFilesz := (lastDataSection.Offset - firstDataSection.Offset) + lastDataSection.Size
45+
allDataMemsz := (lastDataSection.Addr - firstDataSection.Addr) + lastDataSection.Size
46+
47+
if bssSection != nil {
48+
allDataMemsz += align(bssSection.Size, 16);
49+
}
2450
if orbisElf.IsLibrary {
2551
procParamSection = orbisElf.ElfToConvert.Section(".data.sce_module_param")
2652
}
2753

2854
// Get GNU_RELRO header pre-emptively (we'll need to check it to eliminate duplicate PT_LOAD headers)
2955
gnuRelroSegment := orbisElf.getProgramHeader(elf.PT_GNU_RELRO, elf.PF_R)
56+
relroAlignedMemsz := align(gnuRelroSegment.Memsz, 0x4000);
3057

3158
// First pass: drop program headers that we don't need and copy all others
3259
for _, progHeader := range orbisElf.ElfToConvert.Progs {
@@ -38,8 +65,8 @@ func (orbisElf *OrbisElf) GenerateProgramHeaders() error {
3865
// PT_LOAD for relro will be handled by SCE_RELRO, we can get rid of it
3966
if gnuRelroSegment != nil {
4067
if progHeader.Type == elf.PT_LOAD && progHeader.Off == gnuRelroSegment.Off {
41-
if progHeader.Memsz > (gnuRelroSegment.Memsz+0x3fff) & ^uint64(0x4000) {
42-
subtractSize := (gnuRelroSegment.Memsz + 0x3fff) & ^uint64(0x4000)
68+
if progHeader.Memsz > relroAlignedMemsz {
69+
subtractSize := relroAlignedMemsz
4370
progHeader.Off += subtractSize
4471
progHeader.Vaddr += subtractSize
4572
progHeader.Paddr = 0
@@ -88,7 +115,7 @@ func (orbisElf *OrbisElf) GenerateProgramHeaders() error {
88115

89116
// We need to fill the hole between the SCE_RELRO segment and the PT_LOAD segment for .data. Since
90117
// .data.sce_process_param should be the first thing in the data segment, we can use this to calculate.
91-
expandedSize := procParamSection.Offset - progHeader.Off
118+
expandedSize := firstDataSection.Offset - progHeader.Off
92119
progHeader.Filesz = expandedSize
93120
progHeader.Memsz = expandedSize
94121
progHeader.Align = 0x4000
@@ -109,23 +136,13 @@ func (orbisElf *OrbisElf) GenerateProgramHeaders() error {
109136
}
110137
}
111138

112-
// PT_LOAD for data needs to be shifted to contain SCE specific data
139+
// PT_LOAD for read-write data must contain SCE specific data and any read-write `.data` sections
113140
if progHeader.Flags == (elf.PF_R | elf.PF_W) {
114-
// We'll get the size by subtracting the proc param offset from data's offset so we get padding for free, which the
115-
// header size will not provide.
116-
dataSize := (dataSection.Offset - procParamSection.Offset) + dataSection.Size
117-
dataMemSize := (dataSection.Addr - procParamSection.Addr) + dataSection.Size
118-
119-
// Also check for .bss - if it exists, factor it into the size
120-
if bssSection != nil {
121-
dataMemSize += (bssSection.Addr - (dataSection.Addr + dataSection.Size)) + bssSection.Size
122-
}
123-
124-
progHeader.Off = procParamSection.Offset
125-
progHeader.Vaddr = procParamSection.Addr
126-
progHeader.Paddr = procParamSection.Addr
127-
progHeader.Filesz = dataSize
128-
progHeader.Memsz = dataMemSize
141+
progHeader.Off = firstDataSection.Offset
142+
progHeader.Vaddr = firstDataSection.Addr
143+
progHeader.Paddr = firstDataSection.Addr
144+
progHeader.Filesz = allDataFilesz
145+
progHeader.Memsz = allDataMemsz
129146
}
130147
}
131148
}
@@ -298,3 +315,8 @@ func (s programHeaderList) Swap(i int, j int) {
298315
func (s programHeaderList) Less(i int, j int) bool {
299316
return getProgramHeaderPriority(progHeaderTypeOrder, s[i].ProgHeader.Type, s[i].ProgHeader.Flags) < getProgramHeaderPriority(progHeaderTypeOrder, s[j].Type, s[j].Flags)
300317
}
318+
319+
// align takes a given int and aligns it to a given value. Returns the aligned value.
320+
func align(val uint64, align uint64) uint64 {
321+
return (val + (align - 1)) & ^(align - 1)
322+
}

scripts/build.sh

100644100755
File mode changed.

0 commit comments

Comments
 (0)