summaryrefslogtreecommitdiff
blob: db21d8899ae47ab021a769f05a2b6c23f9bdd329 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
2003-06-17  Alan Modra  <amodra@bigpond.net.au>

	* elf64-ppc.c (ppc64_elf_relocate_section): Correct pcrel section zero.

2003-06-16  Alan Modra  <amodra@bigpond.net.au>

	* elf64-ppc.c (ppc64_elf_relocate_section): When optimizing toctprel
	tls, check that a TOC16_DS or TOC16_LO_DS reloc isn't pointing to a
	dtprel entry.  Ensure TLS_LD DTPMOD reloc has a zero addend.  Write
	got section for RELATIVE relocs.  Fix wrong comment.  Change condition
	under which dynamic relocs update the section contents.

--- bfd/elf64-ppc.c	10 Jun 2003 07:44:09 -0000	1.101
+++ bfd/elf64-ppc.c	16 Jun 2003 10:50:22 -0000	1.102
@@ -7153,7 +7153,11 @@ ppc64_elf_relocate_section (output_bfd, 
 		tls_mask = *toc_tls;
 		if (r_type == R_PPC64_TOC16_DS
 		    || r_type == R_PPC64_TOC16_LO_DS)
-		  goto toctprel;
+		  {
+		    if (tls_mask != 0
+			&& (tls_mask & (TLS_DTPREL | TLS_TPREL)) == 0)
+		      goto toctprel;
+		  }
 		else
 		  {
 		    /* If we found a GD reloc pair, then we might be
@@ -7176,11 +7180,11 @@ ppc64_elf_relocate_section (output_bfd, 
 
 	case R_PPC64_GOT_TPREL16_DS:
 	case R_PPC64_GOT_TPREL16_LO_DS:
-	toctprel:
 	  if (tls_mask != 0
 	      && (tls_mask & TLS_TPREL) == 0)
 	    {
 	      bfd_vma insn;
+	    toctprel:
 	      insn = bfd_get_32 (output_bfd, contents + rel->r_offset - 2);
 	      insn &= 31 << 21;
 	      insn |= 0x3c0d0000;	/* addis 0,13,0 */
@@ -7653,6 +7657,7 @@ ppc64_elf_relocate_section (output_bfd, 
 		    outrel.r_offset = (htab->sgot->output_section->vma
 				       + htab->sgot->output_offset
 				       + off);
+		    outrel.r_addend = rel->r_addend;
 		    if (tls_type & (TLS_LD | TLS_GD))
 		      {
 			outrel.r_addend = 0;
@@ -7665,6 +7670,7 @@ ppc64_elf_relocate_section (output_bfd, 
 			    bfd_elf64_swap_reloca_out (output_bfd,
 						       &outrel, loc);
 			    outrel.r_offset += 8;
+			    outrel.r_addend = rel->r_addend;
 			    outrel.r_info
 			      = ELF64_R_INFO (indx, R_PPC64_DTPREL64);
 			  }
@@ -7674,11 +7680,18 @@ ppc64_elf_relocate_section (output_bfd, 
 		    else if (tls_type == (TLS_TLS | TLS_TPREL))
 		      outrel.r_info = ELF64_R_INFO (indx, R_PPC64_TPREL64);
 		    else if (indx == 0)
-		      outrel.r_info = ELF64_R_INFO (indx, R_PPC64_RELATIVE);
+		      {
+			outrel.r_info = ELF64_R_INFO (indx, R_PPC64_RELATIVE);
+
+			/* Write the .got section contents for the sake
+			   of prelink.  */
+			loc = htab->sgot->contents + off;
+			bfd_put_64 (output_bfd, outrel.r_addend + relocation, loc);
+		      }
 		    else
 		      outrel.r_info = ELF64_R_INFO (indx, R_PPC64_GLOB_DAT);
-		    outrel.r_addend = rel->r_addend;
-		    if (indx == 0)
+
+		    if (indx == 0 && tls_type != (TLS_TLS | TLS_LD))
 		      {
 			outrel.r_addend += relocation;
 			if (tls_type & (TLS_GD | TLS_DTPREL | TLS_TPREL))
@@ -7921,8 +7934,6 @@ ppc64_elf_relocate_section (output_bfd, 
 		     or this is an opd section reloc which must point
 		     at a local function.  */
 		  outrel.r_addend += relocation;
-		  /* ??? why? */
-		  relocate = TRUE;
 		  if (r_type == R_PPC64_ADDR64 || r_type == R_PPC64_TOC)
 		    {
 		      if (is_opd && h != NULL)
@@ -7940,6 +7951,12 @@ ppc64_elf_relocate_section (output_bfd, 
 			  unresolved_reloc = FALSE;
 			}
 		      outrel.r_info = ELF64_R_INFO (0, R_PPC64_RELATIVE);
+
+		      /* We need to relocate .opd contents for ld.so.
+			 Prelink also wants simple and consistent rules
+			 for relocs.  This make all RELATIVE relocs have
+			 *r_offset equal to r_addend.  */
+		      relocate = TRUE;
 		    }
 		  else
 		    {
@@ -7981,9 +7998,29 @@ ppc64_elf_relocate_section (output_bfd, 
 
 	      /* If this reloc is against an external symbol, it will
 		 be computed at runtime, so there's no need to do
-		 anything now.  */
+		 anything now.  However, for the sake of prelink ensure
+		 that the section contents are a known value.  */
 	      if (! relocate)
-		continue;
+		{
+		  unresolved_reloc = FALSE;
+		  /* The value chosen here is quite arbitrary as ld.so
+		     ignores section contents except for the special
+		     case of .opd where the contents might be accessed
+		     before relocation.  Choose zero, as that won't
+		     cause reloc overflow.  */
+		  relocation = 0;
+		  addend = 0;
+		  /* Use *r_offset == r_addend for R_PPC64_ADDR64 relocs
+		     to improve backward compatibility with older
+		     versions of ld.  */
+		  if (r_type == R_PPC64_ADDR64)
+		    addend = outrel.r_addend;
+		  /* Adjust pc_relative relocs to have zero in *r_offset.  */
+		  else if (ppc64_elf_howto_table[(int) r_type]->pc_relative)
+		    addend = (input_section->output_section->vma
+			      + input_section->output_offset
+			      + rel->r_offset);
+		}
 	    }
 	  break;