- int pos;
- struct bound_minimal_symbol msymbol;
-
- /* Find backward an address which is a symbol and for which
- disassembling from that address will fill completely the
- window. */
- pos = max_lines - 1;
- do {
- new_low -= 1 * max_lines;
- msymbol = lookup_minimal_symbol_by_pc_section (new_low, 0);
-
- if (msymbol.minsym)
- new_low = BMSYMBOL_VALUE_ADDRESS (msymbol);
- else
- new_low += 1 * max_lines;
-
- tui_disassemble (gdbarch, asm_lines, new_low, max_lines);
- last_addr = asm_lines[pos].addr;
- } while (last_addr > pc && msymbol.minsym);
+
+ /* And this will hold the address of the next instruction that would
+ have been disassembled. */
+ CORE_ADDR next_addr;
+
+ /* As we search backward if we find an address that looks like a
+ promising starting point then we record it in this structure. If
+ the next address we try is not a suitable starting point then we
+ will fall back to the address held here. */
+ gdb::optional<CORE_ADDR> possible_new_low;
+
+ /* The previous value of NEW_LOW so we know if the new value is
+ different or not. */
+ CORE_ADDR prev_low;
+
+ do
+ {
+ /* Find an address from which we can start disassembling. */
+ prev_low = new_low;
+ new_low = tui_find_backward_disassembly_start_address (new_low);
+
+ /* Disassemble forward. */
+ next_addr = tui_disassemble (gdbarch, asm_lines, new_low, max_lines);
+ last_addr = asm_lines.back ().addr;
+
+ /* If disassembling from the current value of NEW_LOW reached PC
+ (or went past it) then this would do as a starting point if we
+ can't find anything better, so remember it. */
+ if (last_addr >= pc && new_low != prev_low
+ && asm_lines.size () >= max_lines)
+ possible_new_low.emplace (new_low);
+
+ /* Continue searching until we find a value of NEW_LOW from which
+ disassembling MAX_LINES instructions doesn't reach PC. We
+ know this means we can find the required number of previous
+ instructions then. */
+ }
+ while ((last_addr > pc
+ || (last_addr == pc && asm_lines.size () < max_lines))
+ && new_low != prev_low);
+
+ /* If we failed to disassemble the required number of lines then the
+ following walk forward is not going to work, it assumes that
+ ASM_LINES contains exactly MAX_LINES entries. Instead we should
+ consider falling back to a previous possible start address in
+ POSSIBLE_NEW_LOW. */
+ if (asm_lines.size () < max_lines)
+ {
+ if (!possible_new_low.has_value ())
+ return pc;
+
+ /* Take the best possible match we have. */
+ new_low = *possible_new_low;
+ next_addr = tui_disassemble (gdbarch, asm_lines, new_low, max_lines);
+ last_addr = asm_lines.back ().addr;
+ gdb_assert (asm_lines.size () >= max_lines);
+ }