@@ -35,6 +35,7 @@ class NativeLinker
3535 readonly TaskLoggingHelper log ;
3636 readonly string abi ;
3737 readonly string ld ;
38+ readonly string objcopy ;
3839 readonly string intermediateDir ;
3940 readonly CancellationToken ? cancellationToken ;
4041 readonly Action ? cancelTask ;
@@ -52,6 +53,7 @@ public NativeLinker (TaskLoggingHelper log, string abi, string soname, string bi
5253 this . cancelTask = cancelTask ;
5354
5455 ld = Path . Combine ( binutilsDir , MonoAndroidHelper . GetExecutablePath ( binutilsDir , "ld" ) ) ;
56+ objcopy = Path . Combine ( binutilsDir , MonoAndroidHelper . GetExecutablePath ( binutilsDir , "llvm-objcopy" ) ) ;
5557
5658 extraArgs . Add ( $ "-soname { soname } ") ;
5759
@@ -142,6 +144,11 @@ public bool Link (ITaskItem outputLibraryPath, List<ITaskItem> objectFiles, List
142144 watch . Stop ( ) ;
143145 log . LogDebugMessage ( $ "[{ Path . GetFileName ( outputLibraryPath . ItemSpec ) } link time] { watch . Elapsed } ") ;
144146
147+ if ( ! ret || ! SaveDebugSymbols ) {
148+ return ret ;
149+ }
150+
151+ ret = ExtractDebugSymbols ( outputLibraryPath ) ;
145152 return ret ;
146153
147154 void WriteFilesToResponseFile ( StreamWriter sw , List < ITaskItem > files )
@@ -190,12 +197,81 @@ void EnsureCorrectAbi (List<ITaskItem> items)
190197 }
191198 }
192199
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+
193255 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 )
194270 {
195271 using var stdout_completed = new ManualResetEvent ( false ) ;
196272 using var stderr_completed = new ManualResetEvent ( false ) ;
197273 var psi = new ProcessStartInfo ( ) {
198- FileName = ld ,
274+ FileName = binaryPath ,
199275 Arguments = String . Join ( " " , args ) ,
200276 UseShellExecute = false ,
201277 RedirectStandardOutput = true ,
@@ -204,16 +280,13 @@ bool RunLinker (List<string> args, ITaskItem outputSharedLibrary)
204280 WindowStyle = ProcessWindowStyle . Hidden ,
205281 } ;
206282
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 } ") ;
212285
213286 using var proc = new Process ( ) ;
214287 proc . OutputDataReceived += ( s , e ) => {
215288 if ( e . Data != null ) {
216- OnOutputData ( linkerName , s , e ) ;
289+ OnOutputData ( binaryName , s , e ) ;
217290 stdoutLines . Add ( e . Data ) ;
218291 } else {
219292 stdout_completed . Set ( ) ;
@@ -222,7 +295,7 @@ bool RunLinker (List<string> args, ITaskItem outputSharedLibrary)
222295
223296 proc . ErrorDataReceived += ( s , e ) => {
224297 if ( e . Data != null ) {
225- OnErrorData ( linkerName , s , e ) ;
298+ OnErrorData ( binaryName , s , e ) ;
226299 stderrLines . Add ( e . Data ) ;
227300 } else {
228301 stderr_completed . Set ( ) ;
@@ -245,8 +318,6 @@ bool RunLinker (List<string> args, ITaskItem outputSharedLibrary)
245318 }
246319
247320 if ( proc . ExitCode != 0 ) {
248- var sb = MonoAndroidHelper . MergeStdoutAndStderrMessages ( stdoutLines , stderrLines ) ;
249- log . LogCodedError ( "XA3007" , Properties . Resources . XA3007 , Path . GetFileName ( outputSharedLibrary . ItemSpec ) , sb . ToString ( ) ) ;
250321 cancelTask ? . Invoke ( ) ;
251322 return false ;
252323 }
0 commit comments