@@ -10,6 +10,7 @@ const FDR_SIZE: usize = 0x48;
1010const PDR_SIZE : usize = 0x34 ;
1111const SYMR_SIZE : usize = 0x0c ;
1212
13+ const ST_LABEL : u8 = 5 ;
1314const ST_PROC : u8 = 6 ;
1415const ST_STATICPROC : u8 = 14 ;
1516const ST_END : u8 = 8 ;
@@ -40,6 +41,8 @@ pub(super) fn parse_line_info_mdebug(
4041 ) ?;
4142 let symbols = parse_symbols ( symbols_data, endianness) ?;
4243
44+ let strings_data = slice_at ( data, header. cb_ss_offset , header. iss_max , section_file_offset) ?;
45+
4346 let fdr_data = slice_at (
4447 data,
4548 header. cb_fd_offset ,
@@ -63,11 +66,13 @@ pub(super) fn parse_line_info_mdebug(
6366 continue ;
6467 }
6568
69+ assign_label_lines ( sections, & symbols[ sym_base..sym_end] , strings_data, & fdr) ;
70+
6671 let Some ( line_file_offset) = header. cb_line_offset . checked_add ( fdr. cb_line_offset ) else {
6772 continue ;
6873 } ;
6974 let Some ( line_file_base) =
70- resolve_offset ( line_file_offset, data. len ( ) , section_file_offset)
75+ resolve_offset ( line_file_offset, fdr . cb_line as usize , data. len ( ) , section_file_offset)
7176 else {
7277 continue ;
7378 } ;
@@ -168,6 +173,44 @@ fn assign_lines(sections: &mut [Section], base_address: u64, lines: &[i32]) {
168173 }
169174}
170175
176+ fn assign_label_lines (
177+ sections : & mut [ Section ] ,
178+ symbols : & [ SymbolEntry ] ,
179+ strings : & [ u8 ] ,
180+ fdr : & FileDescriptor ,
181+ ) {
182+ for sym in symbols {
183+ if sym. st != ST_LABEL || sym. index == 0 {
184+ continue ;
185+ }
186+ let Some ( name) = symbol_name ( strings, fdr. iss_base , sym. iss ) else {
187+ continue ;
188+ } ;
189+ if !name. starts_with ( "$LM" ) {
190+ continue ;
191+ }
192+ let address = fdr. adr as u64 + sym. value as u64 ;
193+ if let Some ( section) = find_code_section ( sections, address) {
194+ section. line_info . insert ( address, sym. index ) ;
195+ }
196+ }
197+ }
198+
199+ fn symbol_name ( strings : & [ u8 ] , file_string_base : u32 , string_offset : u32 ) -> Option < & str > {
200+ let offset =
201+ string_offset. try_into ( ) . ok ( ) . filter ( |& offset: & usize | offset < strings. len ( ) ) . or_else (
202+ || {
203+ file_string_base
204+ . checked_add ( string_offset) ?
205+ . try_into ( )
206+ . ok ( )
207+ . filter ( |& offset: & usize | offset < strings. len ( ) )
208+ } ,
209+ ) ?;
210+ let end = offset + strings[ offset..] . iter ( ) . position ( |& b| b == 0 ) ?;
211+ core:: str:: from_utf8 ( & strings[ offset..end] ) . ok ( )
212+ }
213+
171214fn find_code_section ( sections : & mut [ Section ] , address : u64 ) -> Option < & mut Section > {
172215 sections. iter_mut ( ) . find ( |section| {
173216 section. kind == SectionKind :: Code
@@ -209,12 +252,12 @@ fn slice_at(
209252 let size = size as usize ;
210253 if size == 0 {
211254 ensure ! (
212- resolve_offset( offset, data. len( ) , section_file_offset) . is_some( ) ,
255+ resolve_offset( offset, 0 , data. len( ) , section_file_offset) . is_some( ) ,
213256 "offset outside of .mdebug section"
214257 ) ;
215258 return Ok ( & data[ 0 ..0 ] ) ;
216259 }
217- let Some ( offset) = resolve_offset ( offset, data. len ( ) , section_file_offset) else {
260+ let Some ( offset) = resolve_offset ( offset, size , data. len ( ) , section_file_offset) else {
218261 bail ! ( "offset outside of .mdebug section" ) ;
219262 } ;
220263 let end = offset. checked_add ( size) . context ( "range overflow" ) ?;
@@ -224,26 +267,29 @@ fn slice_at(
224267
225268fn resolve_offset (
226269 offset : u32 ,
270+ size : usize ,
227271 data_len : usize ,
228272 section_file_offset : Option < usize > ,
229273) -> Option < usize > {
230274 let offset = offset as usize ;
231- if offset <= data_len {
232- Some ( offset)
233- } else if let Some ( file_offset) = section_file_offset {
234- offset. checked_sub ( file_offset) . filter ( |rel| * rel <= data_len)
235- } else {
236- None
275+ if let Some ( file_offset) = section_file_offset
276+ && let Some ( rel) = offset. checked_sub ( file_offset)
277+ && rel. checked_add ( size) . is_some_and ( |end| end <= data_len)
278+ {
279+ return Some ( rel) ;
237280 }
281+ offset. checked_add ( size) . filter ( |& end| end <= data_len) . map ( |_| offset)
238282}
239283
240284#[ derive( Clone , Copy ) ]
241285struct Header {
242286 cb_line_offset : u32 ,
243287 cb_pd_offset : u32 ,
244288 cb_sym_offset : u32 ,
289+ cb_ss_offset : u32 ,
245290 cb_fd_offset : u32 ,
246291 isym_max : u32 ,
292+ iss_max : u32 ,
247293 ifd_max : u32 ,
248294}
249295
@@ -267,8 +313,8 @@ impl Header {
267313 let _cb_opt_offset = read_u32 ( data, & mut cursor, endianness) ?;
268314 let _iaux_max = read_u32 ( data, & mut cursor, endianness) ?;
269315 let _cb_aux_offset = read_u32 ( data, & mut cursor, endianness) ?;
270- let _iss_max = read_u32 ( data, & mut cursor, endianness) ?;
271- let _cb_ss_offset = read_u32 ( data, & mut cursor, endianness) ?;
316+ let iss_max = read_u32 ( data, & mut cursor, endianness) ?;
317+ let cb_ss_offset = read_u32 ( data, & mut cursor, endianness) ?;
272318 let _iss_ext_max = read_u32 ( data, & mut cursor, endianness) ?;
273319 let _cb_ss_ext_offset = read_u32 ( data, & mut cursor, endianness) ?;
274320 let ifd_max = read_u32 ( data, & mut cursor, endianness) ?;
@@ -278,13 +324,23 @@ impl Header {
278324 let _iext_max = read_u32 ( data, & mut cursor, endianness) ?;
279325 let _cb_ext_offset = read_u32 ( data, & mut cursor, endianness) ?;
280326
281- Ok ( Header { cb_line_offset, cb_pd_offset, cb_sym_offset, cb_fd_offset, isym_max, ifd_max } )
327+ Ok ( Header {
328+ cb_line_offset,
329+ cb_pd_offset,
330+ cb_sym_offset,
331+ cb_ss_offset,
332+ cb_fd_offset,
333+ isym_max,
334+ iss_max,
335+ ifd_max,
336+ } )
282337 }
283338}
284339
285340#[ derive( Clone , Copy ) ]
286341struct FileDescriptor {
287342 adr : u32 ,
343+ iss_base : u32 ,
288344 isym_base : u32 ,
289345 csym : u32 ,
290346 ipd_first : u16 ,
@@ -299,7 +355,7 @@ impl FileDescriptor {
299355 let mut cursor = 0 ;
300356 let adr = read_u32 ( data, & mut cursor, endianness) ?;
301357 let _rss = read_u32 ( data, & mut cursor, endianness) ?;
302- let _iss_base = read_u32 ( data, & mut cursor, endianness) ?;
358+ let iss_base = read_u32 ( data, & mut cursor, endianness) ?;
303359 let _cb_ss = read_u32 ( data, & mut cursor, endianness) ?;
304360 let isym_base = read_u32 ( data, & mut cursor, endianness) ?;
305361 let csym = read_u32 ( data, & mut cursor, endianness) ?;
@@ -317,7 +373,16 @@ impl FileDescriptor {
317373 let cb_line_offset = read_u32 ( data, & mut cursor, endianness) ?;
318374 let cb_line = read_u32 ( data, & mut cursor, endianness) ?;
319375
320- Ok ( FileDescriptor { adr, isym_base, csym, ipd_first, cpd, cb_line_offset, cb_line } )
376+ Ok ( FileDescriptor {
377+ adr,
378+ iss_base,
379+ isym_base,
380+ csym,
381+ ipd_first,
382+ cpd,
383+ cb_line_offset,
384+ cb_line,
385+ } )
321386 }
322387}
323388
@@ -354,6 +419,7 @@ impl ProcDescriptor {
354419
355420#[ derive( Clone , Copy ) ]
356421struct SymbolEntry {
422+ iss : u32 ,
357423 value : u32 ,
358424 st : u8 ,
359425 index : u32 ,
@@ -364,14 +430,14 @@ fn parse_symbols(data: &[u8], endianness: Endianness) -> Result<Vec<SymbolEntry>
364430 let mut symbols = Vec :: with_capacity ( data. len ( ) / SYMR_SIZE ) ;
365431 let mut cursor = 0 ;
366432 while cursor + SYMR_SIZE <= data. len ( ) {
367- let _iss = read_u32 ( data, & mut cursor, endianness) ?;
433+ let iss = read_u32 ( data, & mut cursor, endianness) ?;
368434 let value = read_u32 ( data, & mut cursor, endianness) ?;
369435 let bits = read_u32 ( data, & mut cursor, endianness) ?;
370436 let ( st, index) = match endianness {
371437 Endianness :: Big => ( ( ( bits >> 26 ) & 0x3f ) as u8 , bits & 0x000f_ffff ) ,
372438 Endianness :: Little => ( ( ( bits & 0x3f ) as u8 ) , ( bits >> 12 ) & 0x000f_ffff ) ,
373439 } ;
374- symbols. push ( SymbolEntry { value, st, index } ) ;
440+ symbols. push ( SymbolEntry { iss , value, st, index } ) ;
375441 }
376442 Ok ( symbols)
377443}
0 commit comments