[RFA,v3,1/2] Make line tables independent of progspace

Message ID 20180426213313.26677-2-tom@tromey.com
State New
Headers show
Series
  • Make line tables independent of progspace
Related show

Commit Message

Tom Tromey April 26, 2018, 9:33 p.m.
This changes line tables to be independent of the program space.

Unlike the corresponding series for minimal symbols, this is a single
patch -- because line tables are used much less frequently than
symbols, it seemed ok to have one patch for the whole conversion.

This patch first renames the fields of the line table, making them
private.  This made it simple to find all users of the fields.  It
adds accessors and setters.

All the setters of the field are updated not to offset the PC by the
section offset.  I think I've done this properly but I can't test all
the spots, unfortunately.

This version includes the change to find_pc_sect_line to "unrelocate"
the PC when searching, speeding up searches a bit.

This patch also cleans up xcoffread.c:compare_lte to make it more
obviously correct.

It was difficult while writing this patch to decide what to do about
gdbarch_addr_bits_remove (and to a lesser extent,
gdbarch_adjust_dwarf2_line).  Previously, all the symbol readers
called this during reading, with the relocated address.  However,
there was an assumption later, in objfile_relocate1, that this did not
need to be re-done after relocation.  So, one option would have been
to call this on the relocated address, and then "unrelocate" it (this
is what I did for gdbarch_adjust_dwarf2_line).  Instead, though, in
this patch I chose to call gdbarch_addr_bits_remove at the point where
the PC is computed.  I'm still not completely certain that this is the
best approach -- please consider this.

While this patch is a step forward, it is still using the backlink
from the symtab to the objfile.  So, more work will be needed in this
area before line tables can be moved to the per-BFD storage.

gdb/ChangeLog
2018-03-21  Tom Tromey  <tom@tromey.com>

	Obsoletes PR symtab/8077:
	* record-btrace.c (btrace_find_line_range): Update.
	* dwarf2read.c (lnp_state_machine::handle_set_address): Remove
	baseaddr argument.
	(dwarf_record_line_1): Don't call gdbarch_addr_bits_remove.
	* buildsym.c (record_line, compare_line_numbers): Update.
	* coffread.c (enter_linenos): Don't add section offset when
	creating line table.
	(coff_symtab_read): Don't call gdbarch_addr_bits_remove.
	* dbxread.c (process_one_symbol): Remove section offset when
	creating line table.
	* disasm.c (do_mixed_source_and_assembly): Update.
	* dwarf2read.c (dwarf_decode_lines_1): Don't add section offset
	when creating line table.
	* jit.c (jit_symtab_line_mapping_add_impl): Update.
	* mdebugread.c (parse_lines, psymtab_to_symtab_1): Don't add
	section offset when creating line table.
	(add_line): Update.
	* mi/mi-symbol-cmds.c (mi_cmd_symbol_list_lines): Update.
	* objfiles.c (objfile_relocate1): Don't relocate line tables.
	* python/py-linetable.c (ltpy_iternext): Update.
	* symmisc.c (dump_symtab_1): Update.
	* symtab.c (find_pc_sect_line, find_pcs_for_symtab_line)
	(skip_prologue_using_lineinfo, skip_prologue_using_sal): Update.
	* symtab.h (struct linetable_entry) <m_pc>: Rename from "pc".
	<m_line>: Rename from "line".
	<set, raw_address, address, line>: New methods.
	* xcoffread.c (compare_lte): Update and rewrite.
	(arrange_linetable): Update.
	(enter_line_range): Don't add section offset when creating line
	table.
---
 gdb/ChangeLog             | 34 ++++++++++++++++
 gdb/buildsym.c            | 12 +++---
 gdb/coffread.c            |  7 +---
 gdb/dbxread.c             | 26 ++++++++-----
 gdb/disasm.c              | 39 +++++++++++--------
 gdb/dwarf2read.c          |  9 +++--
 gdb/jit.c                 |  5 ++-
 gdb/linespec.c            |  2 +-
 gdb/mdebugread.c          | 11 ++----
 gdb/mi/mi-symbol-cmds.c   | 10 +++--
 gdb/objfiles.c            | 17 --------
 gdb/python/py-linetable.c | 11 +++---
 gdb/record-btrace.c       |  5 ++-
 gdb/symmisc.c             |  9 +++--
 gdb/symtab.c              | 98 +++++++++++++++++++++++++++++++----------------
 gdb/symtab.h              | 34 +++++++++++++++-
 gdb/xcoffread.c           | 45 +++++++++++++---------
 17 files changed, 236 insertions(+), 138 deletions(-)

-- 
2.13.6

Patch

diff --git a/gdb/buildsym.c b/gdb/buildsym.c
index 5d38cb250f..f2c08aa530 100644
--- a/gdb/buildsym.c
+++ b/gdb/buildsym.c
@@ -947,7 +947,8 @@  record_line (struct subfile *subfile, int line, CORE_ADDR pc)
   if (line == 0 && subfile->line_vector->nitems > 0)
     {
       e = subfile->line_vector->item + subfile->line_vector->nitems - 1;
-      while (subfile->line_vector->nitems > 0 && e->pc == pc)
+      while (subfile->line_vector->nitems > 0
+	     && e->raw_address () == pc)
 	{
 	  e--;
 	  subfile->line_vector->nitems--;
@@ -955,8 +956,7 @@  record_line (struct subfile *subfile, int line, CORE_ADDR pc)
     }
 
   e = subfile->line_vector->item + subfile->line_vector->nitems++;
-  e->line = line;
-  e->pc = pc;
+  e->set (line, pc);
 }
 
 /* Needed in order to sort line tables from IBM xcoff files.  Sigh!  */
@@ -969,15 +969,15 @@  compare_line_numbers (const void *ln1p, const void *ln2p)
 
   /* Note: this code does not assume that CORE_ADDRs can fit in ints.
      Please keep it that way.  */
-  if (ln1->pc < ln2->pc)
+  if (ln1->raw_address () < ln2->raw_address ())
     return -1;
 
-  if (ln1->pc > ln2->pc)
+  if (ln1->raw_address () > ln2->raw_address ())
     return 1;
 
   /* If pc equal, sort by line.  I'm not sure whether this is optimum
      behavior (see comment at struct linetable in symtab.h).  */
-  return ln1->line - ln2->line;
+  return ln1->line () - ln2->line ();
 }
 
 /* See buildsym.h.  */
diff --git a/gdb/coffread.c b/gdb/coffread.c
index cad3e7e2f1..8408d07bde 100644
--- a/gdb/coffread.c
+++ b/gdb/coffread.c
@@ -1130,8 +1130,7 @@  coff_symtab_read (minimal_symbol_reader &reader,
 	         other statement-line-number.  */
 	      if (fcn_last_line == 1)
 		record_line (current_subfile, fcn_first_line,
-			     gdbarch_addr_bits_remove (gdbarch,
-						       fcn_first_line_addr));
+			     fcn_first_line_addr);
 	      else
 		enter_linenos (fcn_line_ptr, fcn_first_line,
 			       fcn_last_line, objfile);
@@ -1506,11 +1505,9 @@  enter_linenos (long file_offset, int first_line,
       if (L_LNNO32 (&lptr) && L_LNNO32 (&lptr) <= last_line)
 	{
 	  CORE_ADDR addr = lptr.l_addr.l_paddr;
-	  addr += ANOFFSET (objfile->section_offsets,
-			    SECT_OFF_TEXT (objfile));
 	  record_line (current_subfile,
 		       first_line + L_LNNO32 (&lptr),
-		       gdbarch_addr_bits_remove (gdbarch, addr));
+		       addr);
 	}
       else
 	break;
diff --git a/gdb/dbxread.c b/gdb/dbxread.c
index bdf4fb9c79..ff6f9ec20f 100644
--- a/gdb/dbxread.c
+++ b/gdb/dbxread.c
@@ -2562,10 +2562,10 @@  process_one_symbol (int type, int desc, CORE_ADDR valu, const char *name,
 	     but no N_SLINE stabs.  */
 	  if (sline_found_in_function)
 	    {
-	      CORE_ADDR addr = last_function_start + valu;
-
-	      record_line (current_subfile, 0,
-			   gdbarch_addr_bits_remove (gdbarch, addr));
+	      CORE_ADDR addr = (last_function_start + valu
+				- ANOFFSET (section_offsets,
+					    SECT_OFF_TEXT (objfile)));
+	      record_line (current_subfile, 0, addr);
 	    }
 
 	  within_function = 0;
@@ -2767,16 +2767,22 @@  process_one_symbol (int type, int desc, CORE_ADDR valu, const char *name,
 
       if (within_function && sline_found_in_function == 0)
 	{
-	  CORE_ADDR addr = processing_gcc_compilation == 2 ?
-			   last_function_start : valu;
+	  CORE_ADDR addr = ((processing_gcc_compilation == 2 ?
+			     last_function_start : valu)
+			    - ANOFFSET (section_offsets,
+					SECT_OFF_TEXT (objfile)));
 
-	  record_line (current_subfile, desc,
-		       gdbarch_addr_bits_remove (gdbarch, addr));
+	  record_line (current_subfile, desc, addr);
 	  sline_found_in_function = 1;
 	}
       else
-	record_line (current_subfile, desc,
-		     gdbarch_addr_bits_remove (gdbarch, valu));
+	{
+	  CORE_ADDR addr = (valu
+			    - ANOFFSET (section_offsets,
+					SECT_OFF_TEXT (objfile)));
+
+	  record_line (current_subfile, desc, addr);
+	}
       break;
 
     case N_BCOMM:
diff --git a/gdb/disasm.c b/gdb/disasm.c
index 833341a169..97204326d1 100644
--- a/gdb/disasm.c
+++ b/gdb/disasm.c
@@ -30,6 +30,7 @@ 
 #include "safe-ctype.h"
 #include <algorithm>
 #include "common/gdb_optional.h"
+#include "objfiles.h"
 
 /* Disassemble functions.
    FIXME: We should get rid of all the duplicate code in gdb that does
@@ -368,35 +369,39 @@  do_mixed_source_and_assembly_deprecated
 
   /* First, skip all the preceding functions.  */
 
-  for (i = 0; i < nlines - 1 && le[i].pc < low; i++);
+  for (i = 0;
+       i < nlines - 1 && le[i].address (symtab) < low;
+       i++)
+    ;
 
   /* Now, copy all entries before the end of this function.  */
 
-  for (; i < nlines - 1 && le[i].pc < high; i++)
+  for (; i < nlines - 1 && le[i].address (symtab) < high; i++)
     {
-      if (le[i].line == le[i + 1].line && le[i].pc == le[i + 1].pc)
+      if (le[i].line () == le[i + 1].line ()
+	  && le[i].raw_address () == le[i + 1].raw_address ())
 	continue;		/* Ignore duplicates.  */
 
       /* Skip any end-of-function markers.  */
-      if (le[i].line == 0)
+      if (le[i].line () == 0)
 	continue;
 
-      mle[newlines].line = le[i].line;
-      if (le[i].line > le[i + 1].line)
+      mle[newlines].line = le[i].line ();
+      if (le[i].line () > le[i + 1].line ())
 	out_of_order = 1;
-      mle[newlines].start_pc = le[i].pc;
-      mle[newlines].end_pc = le[i + 1].pc;
+      mle[newlines].start_pc = le[i].address (symtab);
+      mle[newlines].end_pc = le[i + 1].address (symtab);
       newlines++;
     }
 
   /* If we're on the last line, and it's part of the function,
      then we need to get the end pc in a special way.  */
 
-  if (i == nlines - 1 && le[i].pc < high)
+  if (i == nlines - 1 && le[i].address (symtab) < high)
     {
-      mle[newlines].line = le[i].line;
-      mle[newlines].start_pc = le[i].pc;
-      sal = find_pc_line (le[i].pc, 0);
+      mle[newlines].line = le[i].line ();
+      mle[newlines].start_pc = le[i].address (symtab);
+      sal = find_pc_line (le[i].address (symtab), 0);
       mle[newlines].end_pc = sal.end;
       newlines++;
     }
@@ -517,10 +522,10 @@  do_mixed_source_and_assembly (struct gdbarch *gdbarch,
   first_le = NULL;
 
   /* Skip all the preceding functions.  */
-  for (i = 0; i < nlines && le[i].pc < low; i++)
-    continue;
+  for (i = 0; i < nlines && le[i].address (main_symtab) < low; i++)
+    ;
 
-  if (i < nlines && le[i].pc < high)
+  if (i < nlines && le[i].address (main_symtab) < high)
     first_le = &le[i];
 
   /* Add lines for every pc value.  */
@@ -589,9 +594,9 @@  do_mixed_source_and_assembly (struct gdbarch *gdbarch,
 	     lines.  */
 	  if (last_line == 0
 	      && first_le != NULL
-	      && first_le->line < sal.line)
+	      && first_le->line () < sal.line)
 	    {
-	      start_preceding_line_to_display = first_le->line;
+	      start_preceding_line_to_display = first_le->line ();
 	      end_preceding_line_to_display = sal.line;
 	    }
 	}
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index 4207e4c531..a8cc3c95e6 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -20311,8 +20311,11 @@  public:
   void handle_set_address (CORE_ADDR baseaddr, CORE_ADDR address)
   {
     m_op_index = 0;
+    /* Pass the relocated address to the gdbarch for modification, but
+       then only store the relative address.  */
     address += baseaddr;
-    m_address = gdbarch_adjust_dwarf2_line (m_gdbarch, address, false);
+    m_address = (gdbarch_adjust_dwarf2_line (m_gdbarch, address, false)
+		 - baseaddr);
   }
 
   /* Handle DW_LNS_advance_pc.  */
@@ -20538,8 +20541,6 @@  dwarf_record_line_1 (struct gdbarch *gdbarch, struct subfile *subfile,
 		     unsigned int line, CORE_ADDR address,
 		     record_line_ftype p_record_line)
 {
-  CORE_ADDR addr = gdbarch_addr_bits_remove (gdbarch, address);
-
   if (dwarf_line_debug)
     {
       fprintf_unfiltered (gdb_stdlog,
@@ -20548,7 +20549,7 @@  dwarf_record_line_1 (struct gdbarch *gdbarch, struct subfile *subfile,
 			  paddress (gdbarch, address));
     }
 
-  (*p_record_line) (subfile, line, addr);
+  (*p_record_line) (subfile, line, address);
 }
 
 /* Subroutine of dwarf_decode_lines_1 to simplify it.
diff --git a/gdb/jit.c b/gdb/jit.c
index 2f23c058a0..eb4579c96b 100644
--- a/gdb/jit.c
+++ b/gdb/jit.c
@@ -622,8 +622,9 @@  jit_symtab_line_mapping_add_impl (struct gdb_symbol_callbacks *cb,
   stab->linetable->nitems = nlines;
   for (i = 0; i < nlines; i++)
     {
-      stab->linetable->item[i].pc = (CORE_ADDR) map[i].pc;
-      stab->linetable->item[i].line = map[i].line;
+      /* Use the absolute address here, as the offsets will all be
+	 zero.  */
+      stab->linetable->item[i].set (map[i].line, (CORE_ADDR) map[i].pc);
     }
 }
 
diff --git a/gdb/linespec.c b/gdb/linespec.c
index 7ef8012ab5..48e2128cf1 100644
--- a/gdb/linespec.c
+++ b/gdb/linespec.c
@@ -2149,7 +2149,7 @@  create_sals_line_offset (struct linespec_state *self,
 	= decode_digits_ordinary (self, ls, val.line, &best_entry);
       if (intermediate_results.empty () && best_entry != NULL)
 	intermediate_results = decode_digits_ordinary (self, ls,
-						       best_entry->line,
+						       best_entry->line (),
 						       &best_entry);
 
       /* For optimized code, the compiler can scatter one source line
diff --git a/gdb/mdebugread.c b/gdb/mdebugread.c
index c0bce55148..a12e459cc6 100644
--- a/gdb/mdebugread.c
+++ b/gdb/mdebugread.c
@@ -2213,7 +2213,7 @@  parse_lines (FDR *fh, PDR *pr, struct linetable *lt, int maxlines,
 	halt = base + fh->cbLine;
       base += pr->cbLineOffset;
 
-      adr = pst->textlow + pr->adr - lowest_pdr_addr;
+      adr = pr->adr - lowest_pdr_addr;
 
       l = adr >> 2;		/* in words */
       for (lineno = pr->lnLow; base < halt;)
@@ -4090,10 +4090,7 @@  psymtab_to_symtab_1 (struct objfile *objfile,
 	      else
 		{
 		  /* Handle encoded stab line number.  */
-		  valu += ANOFFSET (section_offsets,
-				    SECT_OFF_TEXT (objfile));
-		  record_line (current_subfile, sh.index,
-			       gdbarch_addr_bits_remove (gdbarch, valu));
+		  record_line (current_subfile, sh.index, valu);
 		}
 	    }
 	  else if (sh.st == stProc || sh.st == stStaticProc
@@ -4634,8 +4631,8 @@  add_line (struct linetable *lt, int lineno, CORE_ADDR adr, int last)
   if (last == lineno)		/* Skip continuation lines.  */
     return lineno;
 
-  lt->item[lt->nitems].line = lineno;
-  lt->item[lt->nitems++].pc = adr << 2;
+  lt->item[lt->nitems].set (lineno, adr << 2);
+  ++lt->nitems;
   return lineno;
 }
 
diff --git a/gdb/mi/mi-symbol-cmds.c b/gdb/mi/mi-symbol-cmds.c
index 223b8c3ce1..ca0fc379a4 100644
--- a/gdb/mi/mi-symbol-cmds.c
+++ b/gdb/mi/mi-symbol-cmds.c
@@ -34,6 +34,7 @@  mi_cmd_symbol_list_lines (const char *command, char **argv, int argc)
   struct symtab *s;
   int i;
   struct ui_out *uiout = current_uiout;
+  struct linetable *linetable;
 
   if (argc != 1)
     error (_("-symbol-list-lines: Usage: SOURCE_FILENAME"));
@@ -51,11 +52,12 @@  mi_cmd_symbol_list_lines (const char *command, char **argv, int argc)
   gdbarch = get_objfile_arch (SYMTAB_OBJFILE (s));
 
   ui_out_emit_list list_emitter (uiout, "lines");
-  if (SYMTAB_LINETABLE (s) != NULL && SYMTAB_LINETABLE (s)->nitems > 0)
-    for (i = 0; i < SYMTAB_LINETABLE (s)->nitems; i++)
+  linetable = SYMTAB_LINETABLE (s);
+  if (linetable != NULL && linetable->nitems > 0)
+    for (i = 0; i < linetable->nitems; i++)
     {
       ui_out_emit_tuple tuple_emitter (uiout, NULL);
-      uiout->field_core_addr ("pc", gdbarch, SYMTAB_LINETABLE (s)->item[i].pc);
-      uiout->field_int ("line", SYMTAB_LINETABLE (s)->item[i].line);
+      uiout->field_core_addr ("pc", gdbarch, linetable->item[i].address (s));
+      uiout->field_int ("line", linetable->item[i].line ());
     }
 }
diff --git a/gdb/objfiles.c b/gdb/objfiles.c
index 98e81c48c4..0c1d3ffb57 100644
--- a/gdb/objfiles.c
+++ b/gdb/objfiles.c
@@ -799,23 +799,6 @@  objfile_relocate1 (struct objfile *objfile,
   /* OK, get all the symtabs.  */
   {
     struct compunit_symtab *cust;
-    struct symtab *s;
-
-    ALL_OBJFILE_FILETABS (objfile, cust, s)
-    {
-      struct linetable *l;
-      int i;
-
-      /* First the line table.  */
-      l = SYMTAB_LINETABLE (s);
-      if (l)
-	{
-	  for (i = 0; i < l->nitems; ++i)
-	    l->item[i].pc += ANOFFSET (delta,
-				       COMPUNIT_BLOCK_LINE_SECTION
-					 (cust));
-	}
-    }
 
     ALL_OBJFILE_COMPUNITS (objfile, cust)
     {
diff --git a/gdb/python/py-linetable.c b/gdb/python/py-linetable.c
index c4e80d02a5..c17aac31e8 100644
--- a/gdb/python/py-linetable.c
+++ b/gdb/python/py-linetable.c
@@ -20,6 +20,7 @@ 
 #include "defs.h"
 #include "python-internal.h"
 #include "py-ref.h"
+#include "objfiles.h"
 
 typedef struct {
   PyObject_HEAD
@@ -204,7 +205,7 @@  ltpy_has_line (PyObject *self, PyObject *args)
   for (index = 0; index < SYMTAB_LINETABLE (symtab)->nitems; index++)
     {
       struct linetable_entry *item = &(SYMTAB_LINETABLE (symtab)->item[index]);
-      if (item->line == py_line)
+      if (item->line () == py_line)
 	  Py_RETURN_TRUE;
     }
 
@@ -242,9 +243,9 @@  ltpy_get_all_source_lines (PyObject *self, PyObject *args)
 
       /* 0 is used to signify end of line table information.  Do not
 	 include in the source set. */
-      if (item->line > 0)
+      if (item->line () > 0)
 	{
-	  gdbpy_ref<> line (gdb_py_object_from_longest (item->line));
+	  gdbpy_ref<> line (gdb_py_object_from_longest (item->line ()));
 
 	  if (line == NULL)
 	    return NULL;
@@ -410,7 +411,7 @@  ltpy_iternext (PyObject *self)
 
   /* Skip over internal entries such as 0.  0 signifies the end of
      line table data and is not useful to the API user.  */
-  while (item->line < 1)
+  while (item->line () < 1)
     {
       iter_obj->current_index++;
 
@@ -423,7 +424,7 @@  ltpy_iternext (PyObject *self)
       item = &(SYMTAB_LINETABLE (symtab)->item[iter_obj->current_index]);
     }
 
-  obj = build_linetable_entry (item->line, item->pc);
+  obj = build_linetable_entry (item->line (), item->address (symtab));
   iter_obj->current_index++;
 
   return obj;
diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c
index 8736894243..725ff36551 100644
--- a/gdb/record-btrace.c
+++ b/gdb/record-btrace.c
@@ -40,6 +40,7 @@ 
 #include "inf-loop.h"
 #include "vec.h"
 #include <algorithm>
+#include "objfiles.h"
 
 /* The target_ops of record-btrace.  */
 static struct target_ops record_btrace_ops;
@@ -633,8 +634,8 @@  btrace_find_line_range (CORE_ADDR pc)
   range = btrace_mk_line_range (symtab, 0, 0);
   for (i = 0; i < nlines - 1; i++)
     {
-      if ((lines[i].pc == pc) && (lines[i].line != 0))
-	range = btrace_line_range_add (range, lines[i].line);
+      if (lines[i].address (symtab) == pc && lines[i].line () != 0)
+	range = btrace_line_range_add (range, lines[i].line ());
     }
 
   return range;
diff --git a/gdb/symmisc.c b/gdb/symmisc.c
index 9adde044cd..05348b880f 100644
--- a/gdb/symmisc.c
+++ b/gdb/symmisc.c
@@ -302,8 +302,9 @@  dump_symtab_1 (struct symtab *symtab, struct ui_file *outfile)
       len = l->nitems;
       for (i = 0; i < len; i++)
 	{
-	  fprintf_filtered (outfile, " line %d at ", l->item[i].line);
-	  fputs_filtered (paddress (gdbarch, l->item[i].pc), outfile);
+	  fprintf_filtered (outfile, " line %d at ", l->item[i].line ());
+	  fputs_filtered (paddress (gdbarch, l->item[i].address (symtab)),
+			  outfile);
 	  fprintf_filtered (outfile, "\n");
 	}
     }
@@ -1017,8 +1018,8 @@  maintenance_print_one_line_table (struct symtab *symtab, void *data)
 	  struct linetable_entry *item;
 
 	  item = &linetable->item [i];
-	  printf_filtered (_("%-6d %6d %s\n"), i, item->line,
-			   core_addr_to_string (item->pc));
+	  printf_filtered (_("%-6d %6d %s\n"), i, item->line (),
+			   core_addr_to_string (item->address (symtab)));
 	}
     }
 
diff --git a/gdb/symtab.c b/gdb/symtab.c
index c1ead701ec..ad3c4621d0 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -287,6 +287,15 @@  search_domain_name (enum search_domain e)
     }
 }
 
+CORE_ADDR
+linetable_entry::address (struct symtab *symtab) const
+{
+  return gdbarch_addr_bits_remove
+    (get_objfile_arch (SYMTAB_OBJFILE (symtab)),
+     m_pc + ANOFFSET (SYMTAB_OBJFILE (symtab)->section_offsets,
+		      SYMTAB_COMPUNIT (symtab)->block_line_section));
+}
+
 /* See symtab.h.  */
 
 struct symtab *
@@ -3070,6 +3079,7 @@  find_pc_sect_line (CORE_ADDR pc, struct obj_section *section, int notcurrent)
      we will use a line one less than this,
      with a range from the start of that file to the first line's pc.  */
   struct linetable_entry *alt = NULL;
+  struct symtab *alt_symtab = NULL;
 
   /* Info on best line seen in this file.  */
 
@@ -3209,18 +3219,31 @@  find_pc_sect_line (CORE_ADDR pc, struct obj_section *section, int notcurrent)
 
       /* Is this file's first line closer than the first lines of other files?
          If so, record this file, and its first line, as best alternate.  */
-      if (item->pc > pc && (!alt || item->pc < alt->pc))
-	alt = item;
+      if (item->address (iter_s) > pc
+	  && (!alt || (item->address (iter_s) < alt->address (alt_symtab))))
+	{
+	  alt = item;
+	  alt_symtab = iter_s;
+	}
 
-      auto pc_compare = [](const CORE_ADDR & pc,
-			   const struct linetable_entry & lhs)->bool
+      auto pc_compare = [=](const CORE_ADDR & pc,
+			    const struct linetable_entry & lhs)->bool
       {
-	return pc < lhs.pc;
+	return pc < lhs.raw_address ();
       };
 
+      /* We "unrelocate" the incoming PC to make the search
+	 faster.  */
+      CORE_ADDR unrelocated;
+      if (section != nullptr)
+	unrelocated = pc - obj_section_offset (section);
+      else
+	unrelocated = pc - ANOFFSET (SYMTAB_OBJFILE (iter_s)->section_offsets,
+				     SYMTAB_COMPUNIT (iter_s)->block_line_section);
+
       struct linetable_entry *first = item;
       struct linetable_entry *last = item + len;
-      item = std::upper_bound (first, last, pc, pc_compare);
+      item = std::upper_bound (first, last, unrelocated, pc_compare);
       if (item != first)
 	prev = item - 1;		/* Found a matching item.  */
 
@@ -3234,22 +3257,25 @@  find_pc_sect_line (CORE_ADDR pc, struct obj_section *section, int notcurrent)
          save prev if it represents the end of a function (i.e. line number
          0) instead of a real line.  */
 
-      if (prev && prev->line && (!best || prev->pc > best->pc))
+      if (prev
+	  && prev->line ()
+	  && (!best || (prev->address (iter_s) > best->address (best_symtab))))
 	{
 	  best = prev;
 	  best_symtab = iter_s;
 
 	  /* Discard BEST_END if it's before the PC of the current BEST.  */
-	  if (best_end <= best->pc)
+	  if (best_end <= best->address (best_symtab))
 	    best_end = 0;
 	}
 
       /* If another line (denoted by ITEM) is in the linetable and its
 	 PC is after BEST's PC, but before the current BEST_END, then
 	 use ITEM's PC as the new best_end.  */
-      if (best && item < last && item->pc > best->pc
-	  && (best_end == 0 || best_end > item->pc))
-	best_end = item->pc;
+      if (best && item < last
+	  && (item->address (iter_s) > best->address (best_symtab))
+          && (best_end == 0 || best_end > item->address (iter_s)))
+	best_end = item->address (iter_s);
     }
 
   if (!best_symtab)
@@ -3260,7 +3286,7 @@  find_pc_sect_line (CORE_ADDR pc, struct obj_section *section, int notcurrent)
 	 don't make some up.  */
       val.pc = pc;
     }
-  else if (best->line == 0)
+  else if (best->line () == 0)
     {
       /* If our best fit is in a range of PC's for which no line
 	 number info is available (line number is zero) then we didn't
@@ -3270,12 +3296,12 @@  find_pc_sect_line (CORE_ADDR pc, struct obj_section *section, int notcurrent)
   else
     {
       val.symtab = best_symtab;
-      val.line = best->line;
-      val.pc = best->pc;
-      if (best_end && (!alt || best_end < alt->pc))
+      val.line = best->line ();
+      val.pc = best->address (best_symtab);
+      if (best_end && (!alt || best_end < alt->address (alt_symtab)))
 	val.end = best_end;
       else if (alt)
-	val.end = alt->pc;
+	val.end = alt->address (alt_symtab);
       else
 	val.end = BLOCK_END (BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK));
     }
@@ -3355,7 +3381,7 @@  find_line_symtab (struct symtab *symtab, int line,
       struct symtab *s;
 
       if (best_index >= 0)
-	best = best_linetable->item[best_index].line;
+	best = best_linetable->item[best_index].line ();
       else
 	best = 0;
 
@@ -3387,9 +3413,9 @@  find_line_symtab (struct symtab *symtab, int line,
 		best_symtab = s;
 		goto done;
 	      }
-	    if (best == 0 || l->item[ind].line < best)
+	    if (best == 0 || l->item[ind].line () < best)
 	      {
-		best = l->item[ind].line;
+		best = l->item[ind].line ();
 		best_index = ind;
 		best_linetable = l;
 		best_symtab = s;
@@ -3419,6 +3445,7 @@  find_pcs_for_symtab_line (struct symtab *symtab, int line,
 {
   int start = 0;
   std::vector<CORE_ADDR> result;
+  struct linetable *linetable = SYMTAB_LINETABLE (symtab);
 
   /* First, collect all the PCs that are at this line.  */
   while (1)
@@ -3426,22 +3453,21 @@  find_pcs_for_symtab_line (struct symtab *symtab, int line,
       int was_exact;
       int idx;
 
-      idx = find_line_common (SYMTAB_LINETABLE (symtab), line, &was_exact,
-			      start);
+      idx = find_line_common (linetable, line, &was_exact, start);
       if (idx < 0)
 	break;
 
       if (!was_exact)
 	{
-	  struct linetable_entry *item = &SYMTAB_LINETABLE (symtab)->item[idx];
+	  struct linetable_entry *item = &linetable->item[idx];
 
-	  if (*best_item == NULL || item->line < (*best_item)->line)
+	  if (*best_item == NULL || item->line () < (*best_item)->line ())
 	    *best_item = item;
 
 	  break;
 	}
 
-      result.push_back (SYMTAB_LINETABLE (symtab)->item[idx].pc);
+      result.push_back (linetable->item[idx].address (symtab));
       start = idx + 1;
     }
 
@@ -3467,7 +3493,7 @@  find_line_pc (struct symtab *symtab, int line, CORE_ADDR *pc)
   if (symtab != NULL)
     {
       l = SYMTAB_LINETABLE (symtab);
-      *pc = l->item[ind].pc;
+      *pc = l->item[ind].address (symtab);
       return 1;
     }
   else
@@ -3546,16 +3572,16 @@  find_line_common (struct linetable *l, int lineno,
     {
       struct linetable_entry *item = &(l->item[i]);
 
-      if (item->line == lineno)
+      if (item->line () == lineno)
 	{
 	  /* Return the first (lowest address) entry which matches.  */
 	  *exact_match = 1;
 	  return i;
 	}
 
-      if (item->line > lineno && (best == 0 || item->line < best))
+      if (item->line () > lineno && (best == 0 || item->line () < best))
 	{
-	  best = item->line;
+	  best = item->line ();
 	  best_index = i;
 	}
     }
@@ -3656,8 +3682,10 @@  skip_prologue_using_lineinfo (CORE_ADDR func_addr, struct symtab *symtab)
       /* Don't use line numbers of zero, they mark special entries in
 	 the table.  See the commentary on symtab.h before the
 	 definition of struct linetable.  */
-      if (item->line > 0 && func_start <= item->pc && item->pc < func_end)
-	return item->pc;
+      if (item->line () > 0
+	  && func_start <= item->address (symtab)
+	  && item->address (symtab) < func_end)
+	return item->address (symtab);
     }
 
   return func_addr;
@@ -3878,13 +3906,15 @@  skip_prologue_using_sal (struct gdbarch *gdbarch, CORE_ADDR func_addr)
 
 	  /* Skip any earlier lines, and any end-of-sequence marker
 	     from a previous function.  */
-	  while (linetable->item[idx].pc != prologue_sal.pc
-		 || linetable->item[idx].line == 0)
+	  while ((linetable->item[idx].address (prologue_sal.symtab)
+		  != prologue_sal.pc)
+		 || linetable->item[idx].line () == 0)
 	    idx++;
 
 	  if (idx+1 < linetable->nitems
-	      && linetable->item[idx+1].line != 0
-	      && linetable->item[idx+1].pc == start_pc)
+	      && linetable->item[idx+1].line () != 0
+	      && (linetable->item[idx+1].address (prologue_sal.symtab)
+		  == start_pc))
 	    return start_pc;
 	}
 
diff --git a/gdb/symtab.h b/gdb/symtab.h
index f9d52e7697..e85392242c 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -29,6 +29,7 @@ 
 #include "common/function-view.h"
 #include "common/gdb_optional.h"
 #include "completer.h"
+#include "gdbarch.h"
 
 /* Opaque declarations.  */
 struct ui_file;
@@ -1227,8 +1228,37 @@  struct rust_vtable_symbol : public symbol
 
 struct linetable_entry
 {
-  int line;
-  CORE_ADDR pc;
+  /* Set the members of this object.  */
+  void set (int line_, CORE_ADDR pc)
+  {
+    m_line = line_;
+    m_pc = pc;
+  }
+
+  /* Return the raw address.  */
+  CORE_ADDR raw_address () const
+  {
+    return m_pc;
+  }
+
+  /* Return the relocated address, using the offsets provided by
+     SYMTAB.  */
+  CORE_ADDR address (struct symtab *symtab) const;
+
+  /* Return the line number.  */
+  int line () const
+  {
+    return m_line;
+  }
+
+private:
+
+  int m_line;
+
+  /* Note that the PC as stored is unrelocated.  The appropriate
+     offset must be applied before it can be used; see the "address"
+     method.  */
+  CORE_ADDR m_pc;
 };
 
 /* The order of entries in the linetable is significant.  They should
diff --git a/gdb/xcoffread.c b/gdb/xcoffread.c
index 8c707aa8fe..981f7f0716 100644
--- a/gdb/xcoffread.c
+++ b/gdb/xcoffread.c
@@ -420,7 +420,11 @@  compare_lte (const void *lte1p, const void *lte2p)
   struct linetable_entry *lte1 = (struct linetable_entry *) lte1p;
   struct linetable_entry *lte2 = (struct linetable_entry *) lte2p;
 
-  return lte1->pc - lte2->pc;
+  if (lte1->raw_address () < lte2->raw_address ())
+    return -1;
+  if (lte1->raw_address () > lte2->raw_address ())
+    return 1;
+  return 0;
 }
 
 /* Given a line table with function entries are marked, arrange its
@@ -448,7 +452,7 @@  arrange_linetable (struct linetable *oldLineTb)
 
   for (function_count = 0, ii = 0; ii < oldLineTb->nitems; ++ii)
     {
-      if (oldLineTb->item[ii].line == 0)
+      if (oldLineTb->item[ii].line () == 0)
 	{			/* Function entry found.  */
 	  if (function_count >= fentry_size)
 	    {			/* Make sure you have room.  */
@@ -457,14 +461,15 @@  arrange_linetable (struct linetable *oldLineTb)
 		xrealloc (fentry,
 			  fentry_size * sizeof (struct linetable_entry));
 	    }
-	  fentry[function_count].line = ii;
-	  fentry[function_count].pc = oldLineTb->item[ii].pc;
+	  fentry[function_count].set (ii,
+				      oldLineTb->item[ii].raw_address ());
 	  ++function_count;
 
 	  /* If the function was compiled with XLC, we may have to add an
              extra line entry later.  Reserve space for that.  */
 	  if (ii + 1 < oldLineTb->nitems
-	      && oldLineTb->item[ii].pc != oldLineTb->item[ii + 1].pc)
+	      && (oldLineTb->item[ii].raw_address ()
+		  != oldLineTb->item[ii + 1].raw_address ()))
 	    extra_lines++;
 	}
     }
@@ -488,9 +493,10 @@  arrange_linetable (struct linetable *oldLineTb)
      a function begin.  */
 
   newline = 0;
-  if (oldLineTb->item[0].line != 0)
+  if (oldLineTb->item[0].line () != 0)
     for (newline = 0;
-    newline < oldLineTb->nitems && oldLineTb->item[newline].line; ++newline)
+	 newline < oldLineTb->nitems && oldLineTb->item[newline].line ();
+	 ++newline)
       newLineTb->item[newline] = oldLineTb->item[newline];
 
   /* Now copy function lines one by one.  */
@@ -499,17 +505,18 @@  arrange_linetable (struct linetable *oldLineTb)
     {
       /* If the function was compiled with XLC, we may have to add an
          extra line to cover the function prologue.  */
-      jj = fentry[ii].line;
+      jj = fentry[ii].line ();
       if (jj + 1 < oldLineTb->nitems
-	  && oldLineTb->item[jj].pc != oldLineTb->item[jj + 1].pc)
+	  && (oldLineTb->item[jj].raw_address ()
+	      != oldLineTb->item[jj + 1].raw_address ()))
 	{
-	  newLineTb->item[newline] = oldLineTb->item[jj];
-	  newLineTb->item[newline].line = oldLineTb->item[jj + 1].line;
+	  newLineTb->item[newline].set (oldLineTb->item[jj + 1].line (),
+					oldLineTb->item[jj].raw_address ());
 	  newline++;
 	}
 
-      for (jj = fentry[ii].line + 1;
-	   jj < oldLineTb->nitems && oldLineTb->item[jj].line != 0;
+      for (jj = fentry[ii].line () + 1;
+	   jj < oldLineTb->nitems && oldLineTb->item[jj].line () != 0;
 	   ++jj, ++newline)
 	newLineTb->item[newline] = oldLineTb->item[jj];
     }
@@ -871,6 +878,8 @@  enter_line_range (struct subfile *subfile, unsigned beginoffset,
 
   while (curoffset <= limit_offset)
     {
+      CORE_ADDR relocated;
+
       bfd_seek (abfd, curoffset, SEEK_SET);
       bfd_bread (ext_lnno, linesz, abfd);
       bfd_coff_swap_lineno_in (abfd, ext_lnno, &int_lnno);
@@ -879,20 +888,20 @@  enter_line_range (struct subfile *subfile, unsigned beginoffset,
       addr = (int_lnno.l_lnno
 	      ? int_lnno.l_addr.l_paddr
 	      : read_symbol_nvalue (int_lnno.l_addr.l_symndx));
-      addr += ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
 
-      if (addr < startaddr || (endaddr && addr >= endaddr))
+      relocated = (addr + ANOFFSET (objfile->section_offsets,
+				    SECT_OFF_TEXT (objfile)));
+      if (relocated < startaddr || (endaddr && relocated >= endaddr))
 	return;
 
       if (int_lnno.l_lnno == 0)
 	{
 	  *firstLine = read_symbol_lineno (int_lnno.l_addr.l_symndx);
-	  record_line (subfile, 0, gdbarch_addr_bits_remove (gdbarch, addr));
+	  record_line (subfile, 0, addr);
 	  --(*firstLine);
 	}
       else
-	record_line (subfile, *firstLine + int_lnno.l_lnno,
-		     gdbarch_addr_bits_remove (gdbarch, addr));
+	record_line (subfile, *firstLine + int_lnno.l_lnno, addr);
       curoffset += linesz;
     }
 }