@@ -35,6 +35,7 @@ class NativeLinker
35
35
readonly TaskLoggingHelper log ;
36
36
readonly string abi ;
37
37
readonly string ld ;
38
+ readonly string objcopy ;
38
39
readonly string intermediateDir ;
39
40
readonly CancellationToken ? cancellationToken ;
40
41
readonly Action ? cancelTask ;
@@ -52,6 +53,7 @@ public NativeLinker (TaskLoggingHelper log, string abi, string soname, string bi
52
53
this . cancelTask = cancelTask ;
53
54
54
55
ld = Path . Combine ( binutilsDir , MonoAndroidHelper . GetExecutablePath ( binutilsDir , "ld" ) ) ;
56
+ objcopy = Path . Combine ( binutilsDir , MonoAndroidHelper . GetExecutablePath ( binutilsDir , "llvm-objcopy" ) ) ;
55
57
56
58
extraArgs . Add ( $ "-soname { soname } ") ;
57
59
@@ -142,6 +144,11 @@ public bool Link (ITaskItem outputLibraryPath, List<ITaskItem> objectFiles, List
142
144
watch . Stop ( ) ;
143
145
log . LogDebugMessage ( $ "[{ Path . GetFileName ( outputLibraryPath . ItemSpec ) } link time] { watch . Elapsed } ") ;
144
146
147
+ if ( ! ret || ! SaveDebugSymbols ) {
148
+ return ret ;
149
+ }
150
+
151
+ ret = ExtractDebugSymbols ( outputLibraryPath ) ;
145
152
return ret ;
146
153
147
154
void WriteFilesToResponseFile ( StreamWriter sw , List < ITaskItem > files )
@@ -190,12 +197,81 @@ void EnsureCorrectAbi (List<ITaskItem> items)
190
197
}
191
198
}
192
199
200
+ bool ExtractDebugSymbols ( ITaskItem outputSharedLibrary )
201
+ {
202
+ var stdoutLines = new List < string > ( ) ;
203
+ var stderrLines = new List < string > ( ) ;
204
+
205
+ string sourceLib = outputSharedLibrary . ItemSpec ;
206
+ string sourceLibQuoted = MonoAndroidHelper . QuoteFileNameArgument ( sourceLib ) ;
207
+ string destLib = Path . Combine ( Path . GetDirectoryName ( sourceLib ) , $ "{ Path . GetFileNameWithoutExtension ( sourceLib ) } .dbg.so") ;
208
+ string destLibQuoted = MonoAndroidHelper . QuoteFileNameArgument ( destLib ) ;
209
+
210
+ var args = new List < string > {
211
+ "--only-keep-debug" ,
212
+ sourceLibQuoted ,
213
+ destLibQuoted ,
214
+ } ;
215
+
216
+ if ( ! RunCommand ( "Extract Debug Info" , objcopy , args , stdoutLines , stderrLines ) ) {
217
+ LogFailure ( ) ;
218
+ return false ;
219
+ }
220
+
221
+ stdoutLines . Clear ( ) ;
222
+ stderrLines . Clear ( ) ;
223
+ args . Clear ( ) ;
224
+ args . Add ( "--strip-debug" ) ;
225
+ args . Add ( "--strip-unneeded" ) ;
226
+ args . Add ( sourceLibQuoted ) ;
227
+
228
+ if ( ! RunCommand ( "Strip Debug Info" , objcopy , args , stdoutLines , stderrLines ) ) {
229
+ LogFailure ( ) ;
230
+ return false ;
231
+ }
232
+
233
+ stdoutLines . Clear ( ) ;
234
+ stderrLines . Clear ( ) ;
235
+ args . Clear ( ) ;
236
+ args . Add ( $ "--add-gnu-debuglink={ destLibQuoted } ") ;
237
+ args . Add ( sourceLibQuoted ) ;
238
+
239
+ if ( ! RunCommand ( "Add Debug Info Link" , objcopy , args , stdoutLines , stderrLines ) ) {
240
+ LogFailure ( ) ;
241
+ return false ;
242
+ }
243
+
244
+ return true ;
245
+
246
+ void LogFailure ( )
247
+ {
248
+ var sb = MonoAndroidHelper . MergeStdoutAndStderrMessages ( stdoutLines , stderrLines ) ;
249
+ // TODO: consider making it a warning
250
+ // TODO: make it a coded message
251
+ log . LogError ( "Failed to extract debug info" , Path . GetFileName ( sourceLib ) , sb . ToString ( ) ) ;
252
+ }
253
+ }
254
+
193
255
bool RunLinker ( List < string > args , ITaskItem outputSharedLibrary )
256
+ {
257
+ var stdoutLines = new List < string > ( ) ;
258
+ var stderrLines = new List < string > ( ) ;
259
+
260
+ if ( ! RunCommand ( "Native Linker" , ld , args , stdoutLines , stderrLines ) ) {
261
+ var sb = MonoAndroidHelper . MergeStdoutAndStderrMessages ( stdoutLines , stderrLines ) ;
262
+ log . LogCodedError ( "XA3007" , Properties . Resources . XA3007 , Path . GetFileName ( outputSharedLibrary . ItemSpec ) , sb . ToString ( ) ) ;
263
+ return false ;
264
+ }
265
+
266
+ return true ;
267
+ }
268
+
269
+ bool RunCommand ( string label , string binaryPath , List < string > args , List < string > stdoutLines , List < string > stderrLines )
194
270
{
195
271
using var stdout_completed = new ManualResetEvent ( false ) ;
196
272
using var stderr_completed = new ManualResetEvent ( false ) ;
197
273
var psi = new ProcessStartInfo ( ) {
198
- FileName = ld ,
274
+ FileName = binaryPath ,
199
275
Arguments = String . Join ( " " , args ) ,
200
276
UseShellExecute = false ,
201
277
RedirectStandardOutput = true ,
@@ -204,16 +280,13 @@ bool RunLinker (List<string> args, ITaskItem outputSharedLibrary)
204
280
WindowStyle = ProcessWindowStyle . Hidden ,
205
281
} ;
206
282
207
- string linkerName = Path . GetFileName ( ld ) ;
208
- log . LogDebugMessage ( $ "[Native Linker] { psi . FileName } { psi . Arguments } ") ;
209
-
210
- var stdoutLines = new List < string > ( ) ;
211
- var stderrLines = new List < string > ( ) ;
283
+ string binaryName = Path . GetFileName ( ld ) ;
284
+ log . LogDebugMessage ( $ "[{ label } ] { psi . FileName } { psi . Arguments } ") ;
212
285
213
286
using var proc = new Process ( ) ;
214
287
proc . OutputDataReceived += ( s , e ) => {
215
288
if ( e . Data != null ) {
216
- OnOutputData ( linkerName , s , e ) ;
289
+ OnOutputData ( binaryName , s , e ) ;
217
290
stdoutLines . Add ( e . Data ) ;
218
291
} else {
219
292
stdout_completed . Set ( ) ;
@@ -222,7 +295,7 @@ bool RunLinker (List<string> args, ITaskItem outputSharedLibrary)
222
295
223
296
proc . ErrorDataReceived += ( s , e ) => {
224
297
if ( e . Data != null ) {
225
- OnErrorData ( linkerName , s , e ) ;
298
+ OnErrorData ( binaryName , s , e ) ;
226
299
stderrLines . Add ( e . Data ) ;
227
300
} else {
228
301
stderr_completed . Set ( ) ;
@@ -245,8 +318,6 @@ bool RunLinker (List<string> args, ITaskItem outputSharedLibrary)
245
318
}
246
319
247
320
if ( proc . ExitCode != 0 ) {
248
- var sb = MonoAndroidHelper . MergeStdoutAndStderrMessages ( stdoutLines , stderrLines ) ;
249
- log . LogCodedError ( "XA3007" , Properties . Resources . XA3007 , Path . GetFileName ( outputSharedLibrary . ItemSpec ) , sb . ToString ( ) ) ;
250
321
cancelTask ? . Invoke ( ) ;
251
322
return false ;
252
323
}
0 commit comments