[1/2] make line tables independent of progspace

Message ID 1402602493-22018-2-git-send-email-tromey@redhat.com
State New, archived
Headers

Commit Message

Tom Tromey June 12, 2014, 7:48 p.m. UTC
  This changes line tables to be independent of the program space.

Ordinarily I would probably have split this patch into several pieces.
However, since 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 "pc" field of the line table.  This made
it simple to find all users of the field.  It adds accessors and
setters for the new field.

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 patch also cleans up xcoffread.c:compare_lte to make it more
obviously correct.

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 in the future.

2014-06-12  Tom Tromey  <tromey@redhat.com>

	* buildsym.c (record_line, compare_line_numbers): Update.
	* coffread.c (enter_linenos): Don't add section offset when
	creating line table.
	* 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".
	(SET_LINETABLE_ENTRY_ADDRESS, LINETABLE_ENTRY_RAW_ADDRESS)
	(LINETABLE_ENTRY_ADDRESS): New macros.
	* xcoffread.c (compare_lte): Update and rewrite.
	(arrange_linetable): Update.
	(enter_line_range): Don't add section offset when creating line
	table.
---
 gdb/ChangeLog             | 28 ++++++++++++++++++++++++
 gdb/buildsym.c            |  9 ++++----
 gdb/coffread.c            |  2 --
 gdb/dbxread.c             | 21 +++++++++++++-----
 gdb/disasm.c              | 22 ++++++++++++-------
 gdb/dwarf2read.c          |  4 ----
 gdb/jit.c                 |  5 ++++-
 gdb/mdebugread.c          |  7 +++---
 gdb/mi/mi-symbol-cmds.c   | 12 ++++++----
 gdb/objfiles.c            |  9 --------
 gdb/python/py-linetable.c |  4 +++-
 gdb/symmisc.c             |  5 ++++-
 gdb/symtab.c              | 56 +++++++++++++++++++++++++++++++----------------
 gdb/symtab.h              | 14 +++++++++++-
 gdb/xcoffread.c           | 23 ++++++++++++++-----
 15 files changed, 151 insertions(+), 70 deletions(-)
  

Patch

diff --git a/gdb/buildsym.c b/gdb/buildsym.c
index b367d18..84f698e 100644
--- a/gdb/buildsym.c
+++ b/gdb/buildsym.c
@@ -803,7 +803,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
+	     && LINETABLE_ENTRY_RAW_ADDRESS (*e) == pc)
 	{
 	  e--;
 	  subfile->line_vector->nitems--;
@@ -812,7 +813,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;
+  SET_LINETABLE_ENTRY_ADDRESS (*e, pc);
 }
 
 /* Needed in order to sort line tables from IBM xcoff files.  Sigh!  */
@@ -825,10 +826,10 @@  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 (LINETABLE_ENTRY_RAW_ADDRESS (*ln1) < LINETABLE_ENTRY_RAW_ADDRESS (*ln2))
     return -1;
 
-  if (ln1->pc > ln2->pc)
+  if (LINETABLE_ENTRY_RAW_ADDRESS (*ln1) > LINETABLE_ENTRY_RAW_ADDRESS (*ln2))
     return 1;
 
   /* If pc equal, sort by line.  I'm not sure whether this is optimum
diff --git a/gdb/coffread.c b/gdb/coffread.c
index c650d61..6b59ff2 100644
--- a/gdb/coffread.c
+++ b/gdb/coffread.c
@@ -1501,8 +1501,6 @@  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));
diff --git a/gdb/dbxread.c b/gdb/dbxread.c
index 5171f50..19f29ef 100644
--- a/gdb/dbxread.c
+++ b/gdb/dbxread.c
@@ -2774,8 +2774,9 @@  process_one_symbol (int type, int desc, CORE_ADDR valu, char *name,
 	     but no N_SLINE stabs.  */
 	  if (sline_found_in_function)
 	    {
-	      CORE_ADDR addr = last_function_start + valu;
-
+	      CORE_ADDR addr = (last_function_start + valu
+				- ANOFFSET (section_offsets,
+					    SECT_OFF_TEXT (objfile)));
 	      record_line (current_subfile, 0,
 			   gdbarch_addr_bits_remove (gdbarch, addr));
 	    }
@@ -2993,16 +2994,24 @@  process_one_symbol (int type, int desc, CORE_ADDR valu, 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));
 	  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,
+		       gdbarch_addr_bits_remove (gdbarch, addr));
+	}
       break;
 
     case N_BCOMM:
diff --git a/gdb/disasm.c b/gdb/disasm.c
index d94225b..4cc84c6 100644
--- a/gdb/disasm.c
+++ b/gdb/disasm.c
@@ -25,6 +25,7 @@ 
 #include "disasm.h"
 #include "gdbcore.h"
 #include "dis-asm.h"
+#include "objfiles.h"
 
 /* Disassemble functions.
    FIXME: We should get rid of all the duplicate code in gdb that does
@@ -223,13 +224,18 @@  do_mixed_source_and_assembly (struct gdbarch *gdbarch, struct ui_out *uiout,
 
   /* First, skip all the preceding functions.  */
 
-  for (i = 0; i < nlines - 1 && le[i].pc < low; i++);
+  for (i = 0;
+       i < nlines - 1 && LINETABLE_ENTRY_ADDRESS (symtab, le[i]) < 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 && LINETABLE_ENTRY_ADDRESS (symtab, le[i]) < 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
+	  && (LINETABLE_ENTRY_RAW_ADDRESS (le[i])
+	      == LINETABLE_ENTRY_RAW_ADDRESS (le[i + 1])))
 	continue;		/* Ignore duplicates.  */
 
       /* Skip any end-of-function markers.  */
@@ -239,19 +245,19 @@  do_mixed_source_and_assembly (struct gdbarch *gdbarch, struct ui_out *uiout,
       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 = LINETABLE_ENTRY_ADDRESS (symtab, le[i]);
+      mle[newlines].end_pc = LINETABLE_ENTRY_ADDRESS (symtab, le[i + 1]);
       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 && LINETABLE_ENTRY_ADDRESS (symtab, le[i]) < high)
     {
       mle[newlines].line = le[i].line;
-      mle[newlines].start_pc = le[i].pc;
-      sal = find_pc_line (le[i].pc, 0);
+      mle[newlines].start_pc = LINETABLE_ENTRY_ADDRESS (symtab, le[i]);
+      sal = find_pc_line (LINETABLE_ENTRY_ADDRESS (symtab, le[i]), 0);
       mle[newlines].end_pc = sal.end;
       newlines++;
     }
diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c
index f078cb4..08254c0 100644
--- a/gdb/dwarf2read.c
+++ b/gdb/dwarf2read.c
@@ -17155,7 +17155,6 @@  dwarf_decode_lines_1 (struct line_header *lh, const char *comp_dir,
   const gdb_byte *line_end;
   unsigned int bytes_read, extended_len;
   unsigned char op_code, extended_op, adj_opcode;
-  CORE_ADDR baseaddr;
   struct objfile *objfile = cu->objfile;
   bfd *abfd = objfile->obfd;
   struct gdbarch *gdbarch = get_objfile_arch (objfile);
@@ -17164,8 +17163,6 @@  dwarf_decode_lines_1 (struct line_header *lh, const char *comp_dir,
   void (*p_record_line) (struct subfile *subfile, int line, CORE_ADDR pc)
     = record_line;
 
-  baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile));
-
   line_ptr = lh->statement_program_start;
   line_end = lh->statement_program_end;
 
@@ -17277,7 +17274,6 @@  dwarf_decode_lines_1 (struct line_header *lh, const char *comp_dir,
 
 		  op_index = 0;
 		  line_ptr += bytes_read;
-		  address += baseaddr;
 		  break;
 		case DW_LNE_define_file:
                   {
diff --git a/gdb/jit.c b/gdb/jit.c
index db6c1b0..411e925 100644
--- a/gdb/jit.c
+++ b/gdb/jit.c
@@ -612,7 +612,10 @@  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;
+      /* Use the absolute address here, as the offsets will all be
+	 zero.  */
+      SET_LINETABLE_ENTRY_ADDRESS (stab->linetable->item[i],
+				   (CORE_ADDR) map[i].pc);
       stab->linetable->item[i].line = map[i].line;
     }
 }
diff --git a/gdb/mdebugread.c b/gdb/mdebugread.c
index c03ac67..ac8bd72 100644
--- a/gdb/mdebugread.c
+++ b/gdb/mdebugread.c
@@ -2205,7 +2205,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;)
@@ -4103,8 +4103,6 @@  psymtab_to_symtab_1 (struct objfile *objfile,
 	      else
 		{
 		  /* Handle encoded stab line number.  */
-		  valu += ANOFFSET (pst->section_offsets,
-				    SECT_OFF_TEXT (objfile));
 		  record_line (current_subfile, sh.index,
 			       gdbarch_addr_bits_remove (gdbarch, valu));
 		}
@@ -4649,7 +4647,8 @@  add_line (struct linetable *lt, int lineno, CORE_ADDR adr, int last)
     return lineno;
 
   lt->item[lt->nitems].line = lineno;
-  lt->item[lt->nitems++].pc = adr << 2;
+  SET_LINETABLE_ENTRY_ADDRESS (lt->item[lt->nitems], adr << 2);
+  ++lt->nitems;
   return lineno;
 }
 
diff --git a/gdb/mi/mi-symbol-cmds.c b/gdb/mi/mi-symbol-cmds.c
index df008f7..e4e23f2 100644
--- a/gdb/mi/mi-symbol-cmds.c
+++ b/gdb/mi/mi-symbol-cmds.c
@@ -35,6 +35,7 @@  mi_cmd_symbol_list_lines (char *command, char **argv, int argc)
   int i;
   struct cleanup *cleanup_stack, *cleanup_tuple;
   struct ui_out *uiout = current_uiout;
+  struct linetable *linetable;
 
   if (argc != 1)
     error (_("-symbol-list-lines: Usage: SOURCE_FILENAME"));
@@ -52,12 +53,15 @@  mi_cmd_symbol_list_lines (char *command, char **argv, int argc)
   gdbarch = get_objfile_arch (s->objfile);
   cleanup_stack = make_cleanup_ui_out_list_begin_end (uiout, "lines");
 
-  if (LINETABLE (s) != NULL && LINETABLE (s)->nitems > 0)
-    for (i = 0; i < LINETABLE (s)->nitems; i++)
+  linetable = LINETABLE (s);
+  if (linetable != NULL && linetable->nitems > 0)
+    for (i = 0; i < linetable->nitems; i++)
     {
       cleanup_tuple = make_cleanup_ui_out_tuple_begin_end (uiout, NULL);
-      ui_out_field_core_addr (uiout, "pc", gdbarch, LINETABLE (s)->item[i].pc);
-      ui_out_field_int (uiout, "line", LINETABLE (s)->item[i].line);
+      ui_out_field_core_addr (uiout, "pc", gdbarch,
+			      LINETABLE_ENTRY_ADDRESS (s,
+						       linetable->item[i]));
+      ui_out_field_int (uiout, "line", linetable->item[i].line);
       do_cleanups (cleanup_tuple);
     }
 
diff --git a/gdb/objfiles.c b/gdb/objfiles.c
index 81bbf24..653ac95 100644
--- a/gdb/objfiles.c
+++ b/gdb/objfiles.c
@@ -745,18 +745,9 @@  objfile_relocate1 (struct objfile *objfile,
 
     ALL_OBJFILE_SYMTABS (objfile, s)
     {
-      struct linetable *l;
       struct blockvector *bv;
       int i;
 
-      /* First the line table.  */
-      l = LINETABLE (s);
-      if (l)
-	{
-	  for (i = 0; i < l->nitems; ++i)
-	    l->item[i].pc += ANOFFSET (delta, s->block_line_section);
-	}
-
       /* Don't relocate a shared blockvector more than once.  */
       if (!s->primary)
 	continue;
diff --git a/gdb/python/py-linetable.c b/gdb/python/py-linetable.c
index 8b5362b..ce2dd9d 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 "exceptions.h"
+#include "objfiles.h"
 
 typedef struct {
   PyObject_HEAD
@@ -448,7 +449,8 @@  ltpy_iternext (PyObject *self)
       item = &(symtab->linetable->item[iter_obj->current_index]);
     }
 
-  obj = build_linetable_entry (item->line, item->pc);
+  obj = build_linetable_entry (item->line,
+			       LINETABLE_ENTRY_ADDRESS (symtab, *item));
   iter_obj->current_index++;
 
   return obj;
diff --git a/gdb/symmisc.c b/gdb/symmisc.c
index 7ea97bd..79d4e82 100644
--- a/gdb/symmisc.c
+++ b/gdb/symmisc.c
@@ -317,7 +317,10 @@  dump_symtab_1 (struct objfile *objfile, struct symtab *symtab,
       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);
+	  fputs_filtered (paddress (gdbarch,
+				    LINETABLE_ENTRY_ADDRESS (symtab,
+							     l->item[i])),
+			  outfile);
 	  fprintf_filtered (outfile, "\n");
 	}
     }
diff --git a/gdb/symtab.c b/gdb/symtab.c
index 66d1624..900198a 100644
--- a/gdb/symtab.c
+++ b/gdb/symtab.c
@@ -2295,6 +2295,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.  */
 
@@ -2440,14 +2441,19 @@  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 (LINETABLE_ENTRY_ADDRESS (s, *item) > pc
+	  && (!alt || (LINETABLE_ENTRY_ADDRESS (s, *item)
+		       < LINETABLE_ENTRY_ADDRESS (alt_symtab, *alt))))
+	{
+	  alt = item;
+	  alt_symtab = s;
+	}
 
       for (i = 0; i < len; i++, item++)
 	{
 	  /* Leave prev pointing to the linetable entry for the last line
 	     that started at or before PC.  */
-	  if (item->pc > pc)
+	  if (LINETABLE_ENTRY_ADDRESS (s, *item) > pc)
 	    break;
 
 	  prev = item;
@@ -2463,22 +2469,26 @@  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 || (LINETABLE_ENTRY_ADDRESS (s, *prev)
+			> LINETABLE_ENTRY_ADDRESS (best_symtab, *best))))
 	{
 	  best = prev;
 	  best_symtab = s;
 
 	  /* Discard BEST_END if it's before the PC of the current BEST.  */
-	  if (best_end <= best->pc)
+	  if (best_end <= LINETABLE_ENTRY_ADDRESS (best_symtab, *best))
 	    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 && i < len && item->pc > best->pc
-          && (best_end == 0 || best_end > item->pc))
-	best_end = item->pc;
+      if (best && i < len && (LINETABLE_ENTRY_ADDRESS (s, *item)
+			      > LINETABLE_ENTRY_ADDRESS (best_symtab, *best))
+          && (best_end == 0 || best_end > LINETABLE_ENTRY_ADDRESS (s, *item)))
+	best_end = LINETABLE_ENTRY_ADDRESS (s, *item);
     }
 
   if (!best_symtab)
@@ -2500,11 +2510,12 @@  find_pc_sect_line (CORE_ADDR pc, struct obj_section *section, int notcurrent)
     {
       val.symtab = best_symtab;
       val.line = best->line;
-      val.pc = best->pc;
-      if (best_end && (!alt || best_end < alt->pc))
+      val.pc = LINETABLE_ENTRY_ADDRESS (best_symtab, *best);
+      if (best_end && (!alt || best_end < LINETABLE_ENTRY_ADDRESS (alt_symtab,
+								   *alt)))
 	val.end = best_end;
       else if (alt)
-	val.end = alt->pc;
+	val.end = LINETABLE_ENTRY_ADDRESS (alt_symtab, *alt);
       else
 	val.end = BLOCK_END (BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK));
     }
@@ -2634,6 +2645,7 @@  find_pcs_for_symtab_line (struct symtab *symtab, int line,
 {
   int start = 0;
   VEC (CORE_ADDR) *result = NULL;
+  struct linetable *linetable = LINETABLE (symtab);
 
   /* First, collect all the PCs that are at this line.  */
   while (1)
@@ -2641,13 +2653,13 @@  find_pcs_for_symtab_line (struct symtab *symtab, int line,
       int was_exact;
       int idx;
 
-      idx = find_line_common (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 = &LINETABLE (symtab)->item[idx];
+	  struct linetable_entry *item = &linetable->item[idx];
 
 	  if (*best_item == NULL || item->line < (*best_item)->line)
 	    *best_item = item;
@@ -2655,7 +2667,8 @@  find_pcs_for_symtab_line (struct symtab *symtab, int line,
 	  break;
 	}
 
-      VEC_safe_push (CORE_ADDR, result, LINETABLE (symtab)->item[idx].pc);
+      VEC_safe_push (CORE_ADDR, result,
+		     LINETABLE_ENTRY_ADDRESS (symtab, linetable->item[idx]));
       start = idx + 1;
     }
 
@@ -2681,7 +2694,7 @@  find_line_pc (struct symtab *symtab, int line, CORE_ADDR *pc)
   if (symtab != NULL)
     {
       l = LINETABLE (symtab);
-      *pc = l->item[ind].pc;
+      *pc = LINETABLE_ENTRY_ADDRESS (symtab, l->item[ind]);
       return 1;
     }
   else
@@ -2822,8 +2835,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 <= LINETABLE_ENTRY_ADDRESS (symtab, *item)
+	  && LINETABLE_ENTRY_ADDRESS (symtab, *item) < func_end)
+	return LINETABLE_ENTRY_ADDRESS (symtab, *item);
     }
 
   return func_addr;
@@ -4944,13 +4959,16 @@  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
+	  while ((LINETABLE_ENTRY_ADDRESS (prologue_sal.symtab,
+					  linetable->item[idx])
+		  != 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_ENTRY_ADDRESS (prologue_sal.symtab,
+					  linetable->item[idx+1]) == start_pc)
 	    return start_pc;
 	}
 
diff --git a/gdb/symtab.h b/gdb/symtab.h
index fbe5868..fcca53a 100644
--- a/gdb/symtab.h
+++ b/gdb/symtab.h
@@ -813,9 +813,21 @@  struct template_symbol
 struct linetable_entry
 {
   int line;
-  CORE_ADDR pc;
+
+  /* Note that the PC as stored is unrelocated.  The appropriate
+     offset must be applied before it can be used.  */
+  CORE_ADDR m_pc;
 };
 
+#define SET_LINETABLE_ENTRY_ADDRESS(ENTRY, PC)		\
+  ((ENTRY).m_pc = (PC))
+#define LINETABLE_ENTRY_RAW_ADDRESS(ENTRY)		\
+  ((ENTRY).m_pc + 0)
+#define LINETABLE_ENTRY_ADDRESS(SYMTAB, ENTRY)		\
+  ((ENTRY).m_pc						\
+   + ANOFFSET ((SYMTAB)->objfile->section_offsets,	\
+	       (SYMTAB)->block_line_section))
+
 /* The order of entries in the linetable is significant.  They should
    be sorted by increasing values of the pc field.  If there is more than
    one entry for a given pc, then I'm not sure what should happen (and
diff --git a/gdb/xcoffread.c b/gdb/xcoffread.c
index b986dbd..812458e 100644
--- a/gdb/xcoffread.c
+++ b/gdb/xcoffread.c
@@ -418,7 +418,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 (LINETABLE_ENTRY_RAW_ADDRESS (*lte1) < LINETABLE_ENTRY_RAW_ADDRESS (*lte2))
+    return -1;
+  if (LINETABLE_ENTRY_RAW_ADDRESS (*lte1) > LINETABLE_ENTRY_RAW_ADDRESS (*lte2))
+    return 1;
+  return 0;
 }
 
 /* Given a line table with function entries are marked, arrange its
@@ -457,13 +461,16 @@  arrange_linetable (struct linetable *oldLineTb)
 			  fentry_size * sizeof (struct linetable_entry));
 	    }
 	  fentry[function_count].line = ii;
-	  fentry[function_count].pc = oldLineTb->item[ii].pc;
+	  SET_LINETABLE_ENTRY_ADDRESS
+	    (fentry[function_count],
+	     LINETABLE_ENTRY_RAW_ADDRESS (oldLineTb->item[ii]));
 	  ++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)
+	      && (LINETABLE_ENTRY_RAW_ADDRESS (oldLineTb->item[ii])
+		  != LINETABLE_ENTRY_RAW_ADDRESS (oldLineTb->item[ii + 1])))
 	    extra_lines++;
 	}
     }
@@ -500,7 +507,8 @@  arrange_linetable (struct linetable *oldLineTb)
          extra line to cover the function prologue.  */
       jj = fentry[ii].line;
       if (jj + 1 < oldLineTb->nitems
-	  && oldLineTb->item[jj].pc != oldLineTb->item[jj + 1].pc)
+	  && (LINETABLE_ENTRY_RAW_ADDRESS (oldLineTb->item[jj])
+	      != LINETABLE_ENTRY_RAW_ADDRESS (oldLineTb->item[jj + 1])))
 	{
 	  newLineTb->item[newline] = oldLineTb->item[jj];
 	  newLineTb->item[newline].line = oldLineTb->item[jj + 1].line;
@@ -878,6 +886,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);
@@ -886,9 +896,10 @@  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)