@@ -1749,7 +1749,7 @@ ranges_inspect(DebugInfoReader *reader, ranges_t *ptr, FILE *errout)
17491749#endif
17501750
17511751static int
1752- di_read_cu (DebugInfoReader * reader , FILE * errout )
1752+ di_read_cu_context (DebugInfoReader * reader , FILE * errout )
17531753{
17541754 uint64_t unit_length ;
17551755 uint16_t version ;
@@ -1784,7 +1784,6 @@ di_read_cu(DebugInfoReader *reader, FILE *errout)
17841784
17851785 reader -> level = 0 ;
17861786 di_read_debug_abbrev_cu (reader );
1787- if (di_read_debug_line_cu (reader , errout )) return -1 ;
17881787
17891788 do {
17901789 DIE die ;
@@ -1840,12 +1839,57 @@ di_read_cu(DebugInfoReader *reader, FILE *errout)
18401839 return 0 ;
18411840}
18421841
1842+ static int
1843+ di_read_cu (DebugInfoReader * reader , FILE * errout )
1844+ {
1845+ /* Keep di_read_cu_context separate so that it can be reused by di_read_cu_at
1846+ * to set up arbitrary CUs without disturbing the .debug_line traversal. */
1847+ if (di_read_cu_context (reader , errout )) return -1 ;
1848+ if (di_read_debug_line_cu (reader , errout )) return -1 ;
1849+ return 0 ;
1850+ }
1851+
1852+ /* Find the .debug_info compilation unit containing the section-relative DIE
1853+ * offset `die_offset`, initialize `reader` with that unit's abbrev/base context,
1854+ * and leave reader->p pointing at the referenced DIE. Type units, split DWARF,
1855+ * and supplementary debug objects are outside this parser's current scope. */
1856+ static bool
1857+ di_read_cu_at (DebugInfoReader * reader , uint64_t die_offset , FILE * errout )
1858+ {
1859+ const uint64_t debug_info_size = reader -> obj -> debug_info .size ;
1860+ if (die_offset >= debug_info_size ) return false;
1861+
1862+ const char * const info = reader -> obj -> debug_info .ptr ;
1863+ const char * const pend = reader -> pend ;
1864+ const char * const target = info + die_offset ;
1865+ const char * cu = info ;
1866+
1867+ while (pend - cu >= 4 ) {
1868+ const char * hp = cu ;
1869+ uint64_t unit_length = read_uint32 (& hp );
1870+
1871+ if (unit_length == 0xffffffff ) {
1872+ if (pend - hp < 8 ) return false;
1873+ unit_length = read_uint64 (& hp );
1874+ }
1875+ if (unit_length == 0 || unit_length > (uint64_t )(pend - hp )) return false;
1876+
1877+ const char * cu_end = hp + unit_length ;
1878+ if (target >= cu && target < cu_end ) {
1879+ reader -> p = cu ;
1880+ if (di_read_cu_context (reader , errout )) return false;
1881+ reader -> p = target ;
1882+ return true;
1883+ }
1884+ cu = cu_end ;
1885+ }
1886+ return false;
1887+ }
1888+
18431889static void
18441890read_abstract_origin (DebugInfoReader * reader , uint64_t form , uint64_t abstract_origin , line_info_t * line , FILE * errout )
18451891{
1846- const char * p = reader -> p ;
1847- const char * q = reader -> q ;
1848- int level = reader -> level ;
1892+ DebugInfoReader saved = * reader ; /* CU-scoped state may be rewritten below */
18491893 DIE die ;
18501894
18511895 switch (form ) {
@@ -1857,7 +1901,11 @@ read_abstract_origin(DebugInfoReader *reader, uint64_t form, uint64_t abstract_o
18571901 reader -> p = reader -> current_cu + abstract_origin ;
18581902 break ;
18591903 case DW_FORM_ref_addr :
1860- goto finish ; /* not supported yet */
1904+ /* Section-relative; target may be in another CU.
1905+ * Switch to that CU's context.
1906+ * di_read_cu_at leaves p at the target DIE. */
1907+ if (!di_read_cu_at (reader , abstract_origin , errout )) goto finish ;
1908+ break ;
18611909 case DW_FORM_ref_sig8 :
18621910 goto finish ; /* not supported yet */
18631911 case DW_FORM_ref_sup4 :
@@ -1880,9 +1928,7 @@ read_abstract_origin(DebugInfoReader *reader, uint64_t form, uint64_t abstract_o
18801928 }
18811929
18821930 finish :
1883- reader -> p = p ;
1884- reader -> q = q ;
1885- reader -> level = level ;
1931+ * reader = saved ;
18861932}
18871933
18881934static bool
@@ -2209,7 +2255,12 @@ fill_lines(int num_traces, void **traces, int check_debuglink,
22092255 }
22102256
22112257 if (obj -> debug_info .ptr && obj -> debug_abbrev .ptr ) {
2212- DebugInfoReader reader ;
2258+ /* Static (not stack): ~2KB struct, runs on a small altstack.
2259+ * Safe despite fill_lines re-entering via follow_debuglink: this
2260+ * block's while loop fully consumes the reader before that
2261+ * recursion point (in the separate !debug_line block below), and
2262+ * debug_info_reader_init reinitializes on each entry. */
2263+ static DebugInfoReader reader ;
22132264 debug_info_reader_init (& reader , obj );
22142265 i = 0 ;
22152266 while (reader .p < reader .pend ) {
@@ -2492,7 +2543,8 @@ fill_lines(int num_traces, void **traces, int check_debuglink,
24922543 }
24932544
24942545 if (obj -> debug_info .ptr && obj -> debug_abbrev .ptr ) {
2495- DebugInfoReader reader ;
2546+ /* Static (not stack): ~2KB struct, runs on a small altstack. */
2547+ static DebugInfoReader reader ;
24962548 debug_info_reader_init (& reader , obj );
24972549 while (reader .p < reader .pend ) {
24982550 if (di_read_cu (& reader , errout )) goto fail ;
0 commit comments