@@ -14,10 +14,10 @@ import Foundation
14
14
import LinuxSystemHeaders
15
15
16
16
class LinkMap {
17
- public enum Error : Swift . Error {
18
- case MalformedElf ( _ description : String )
19
- case MissingAuxVecEntry ( _ description : String )
20
- case ProcessReadMemoryFailure ( address : UInt , _ description: String = " " )
17
+ public enum LinkMapError : Error {
18
+ case failedLoadingAuxVec ( for : pid_t )
19
+ case missingAuxVecEntry ( for : pid_t , _ tag : Int32 )
20
+ case malformedELF ( for : pid_t , _ description: String )
21
21
}
22
22
23
23
public struct Entry {
@@ -28,22 +28,21 @@ class LinkMap {
28
28
public let entries : [ Entry ]
29
29
30
30
public init ( for process: Process ) throws {
31
- guard let auxVec = Self . loadAuxVec ( for: process) else {
32
- throw Error . MissingAuxVecEntry ( " failed reading auxvec for \( process) " )
31
+ let auxVec = try Self . loadAuxVec ( for: process. pid)
32
+ guard let phdrAddr = auxVec [ AT_PHDR] else {
33
+ throw LinkMapError . missingAuxVecEntry ( for: process. pid, AT_PHDR)
33
34
}
34
35
35
- guard let phdrAddr = auxVec [ AT_PHDR] else { throw Error . MissingAuxVecEntry ( " missing AT_PHDR " ) }
36
-
37
36
guard let phdrSize = auxVec [ AT_PHENT] else {
38
- throw Error . MissingAuxVecEntry ( " missing AT_PHENT" )
37
+ throw LinkMapError . missingAuxVecEntry ( for : process . pid , AT_PHENT)
39
38
}
40
39
41
40
guard let phdrCount = auxVec [ AT_PHNUM] else {
42
- throw Error . MissingAuxVecEntry ( " missing AT_PHNUM" )
41
+ throw LinkMapError . missingAuxVecEntry ( for : process . pid , AT_PHNUM)
43
42
}
44
43
45
44
guard phdrSize == MemoryLayout< Elf64_Phdr> . size else {
46
- throw Error . MalformedElf ( " AT_PHENT invalid size: \( phdrSize) " )
45
+ throw LinkMapError . malformedELF ( for : process . pid , " AT_PHENT invalid size: \( phdrSize) " )
47
46
}
48
47
49
48
// determine the base load address for the executable file and locate the
@@ -66,7 +65,7 @@ class LinkMap {
66
65
67
66
case UInt32 ( PT_DYNAMIC) :
68
67
guard dynamicSegment == nil else {
69
- throw Error . MalformedElf ( " multiple PT_DYNAMIC segments found " )
68
+ throw LinkMapError . malformedELF ( for : process . pid , " multiple PT_DYNAMIC segments found " )
70
69
}
71
70
dynamicSegment = phdr
72
71
@@ -75,11 +74,11 @@ class LinkMap {
75
74
}
76
75
77
76
guard let dynamicSegment = dynamicSegment else {
78
- throw Error . MalformedElf ( " PT_DYNAMIC segment not found " )
77
+ throw LinkMapError . malformedELF ( for : process . pid , " PT_DYNAMIC segment not found " )
79
78
}
80
79
81
80
guard let baseLoadSegment = baseLoadSegment else {
82
- throw Error . MalformedElf ( " PT_LOAD segment not found " )
81
+ throw LinkMapError . malformedELF ( for : process . pid , " PT_LOAD segment not found " )
83
82
}
84
83
85
84
let ehdrSize = MemoryLayout< Elf64_Ehdr> . size
@@ -101,7 +100,7 @@ class LinkMap {
101
100
}
102
101
103
102
guard let rDebugEntry = rDebugEntry else {
104
- throw Error . MalformedElf ( " DT_DEBUG not found in dynamic segment " )
103
+ throw LinkMapError . malformedELF ( for : process . pid , " DT_DEBUG not found in dynamic segment " )
105
104
}
106
105
107
106
let rDebugAddr : UInt64 = rDebugEntry. d_un. d_val
@@ -122,8 +121,11 @@ class LinkMap {
122
121
}
123
122
124
123
// loads the auxiliary vector for a 64-bit process
125
- static func loadAuxVec( for process: Process ) -> [ Int32 : UInt64 ] ? {
126
- guard let data = ProcFS . loadFile ( for: process. pid, " auxv " ) else { return nil }
124
+ static func loadAuxVec( for pid: pid_t ) throws -> [ Int32 : UInt64 ] {
125
+ guard let data = ProcFS . loadFile ( for: pid, " auxv " ) else {
126
+ throw LinkMapError . failedLoadingAuxVec ( for: pid)
127
+ }
128
+
127
129
return data. withUnsafeBytes {
128
130
// in a 64-bit process, aux vector is an array of 8-byte pairs
129
131
let count = $0. count / MemoryLayout< ( UInt64, UInt64) > . stride
0 commit comments