4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
27 * Object file dependent support for ELF objects.
31 #include <sys/procfs.h>
39 #include "_inline_gen.h"
43 * For backward compatibility copy relocation processing, it can be necessary to
44 * determine if a copy destination is also the recipient of a move record. For
45 * these instances, the move record addresses are retained for is_move_data().
47 static APlist
*alp
= NULL
;
50 * Warning message for bad move target.
53 elf_move_bad(Lm_list
*lml
, Rt_map
*lmp
, Sym
*sym
, ulong_t num
, Addr addr
)
58 trace
= (lml
->lm_flags
& LML_FLG_TRC_ENABLE
) &&
59 (((rtld_flags
& RT_FL_SILENCERR
) == 0) ||
60 (lml
->lm_flags
& (LML_FLG_TRC_VERBOSE
| LML_FLG_TRC_WARN
)));
62 if ((trace
== 0) && (DBG_ENABLED
== 0))
65 if (ELF_ST_BIND(sym
->st_info
) != STB_LOCAL
)
66 name
= (const char *)(STRTAB(lmp
) + sym
->st_name
);
68 name
= MSG_INTL(MSG_STR_UNKNOWN
);
71 (void) printf(MSG_INTL(MSG_LDD_MOVE_ERR
), EC_XWORD(num
), name
,
74 DBG_CALL(Dbg_move_bad(lml
, num
, name
, addr
));
78 * Move data. Apply sparse initialization to data in zeroed bss.
81 move_data(Rt_map
*lmp
, APlist
**textrel
)
83 Lm_list
*lml
= LIST(lmp
);
84 Move
*mv
= MOVETAB(lmp
);
85 ulong_t num
, mvnum
= MOVESZ(lmp
) / MOVEENT(lmp
);
89 * If these records are against the executable, and the executable was
90 * built prior to Solaris 8, keep track of the move record symbol. See
91 * comment in analyze.c:lookup_sym_interpose() in regards Solaris 8
92 * objects and DT_FLAGS.
94 moves
= (lmp
== lml
->lm_head
) && ((FLAGS1(lmp
) & FL1_RT_DTFLAGS
) == 0);
96 DBG_CALL(Dbg_move_data(lmp
));
97 for (num
= 0; num
< mvnum
; num
++, mv
++) {
98 mmapobj_result_t
*mpp
;
100 Half rep
, repno
, stride
;
103 if ((sym
= (Sym
*)SYMTAB(lmp
) + ELF_M_SYM(mv
->m_info
)) == 0)
106 stride
= mv
->m_stride
+ 1;
107 addr
= sym
->st_value
;
110 * Determine the move data target, and verify the address is
113 if ((FLAGS(lmp
) & FLG_RT_FIXED
) == 0)
115 taddr
= addr
+ mv
->m_poffset
;
117 if ((mpp
= find_segment((caddr_t
)taddr
, lmp
)) == NULL
) {
118 elf_move_bad(lml
, lmp
, sym
, num
, taddr
);
121 if (((mpp
->mr_prot
& PROT_WRITE
) == 0) &&
122 ((set_prot(lmp
, mpp
, 1) == 0) ||
123 (aplist_append(textrel
, mpp
, AL_CNT_TEXTREL
) == NULL
)))
126 DBG_CALL(Dbg_move_entry2(lml
, mv
, sym
->st_name
,
127 (const char *)(sym
->st_name
+ STRTAB(lmp
))));
129 for (rep
= 0, repno
= 0; rep
< mv
->m_repeat
; rep
++) {
130 DBG_CALL(Dbg_move_expand(lml
, mv
, taddr
));
132 switch (ELF_M_SIZE(mv
->m_info
)) {
134 *((char *)taddr
) = (char)mv
->m_value
;
140 *((Half
*)taddr
) = (Half
)mv
->m_value
;
146 *((Word
*)taddr
) = (Word
)mv
->m_value
;
152 *((unsigned long long *)taddr
) = mv
->m_value
;
157 eprintf(lml
, ERR_NONE
, MSG_INTL(MSG_MOVE_ERR1
));
163 * If any move records have been applied to this symbol, retain
164 * the symbol address if required for backward compatibility
165 * copy relocation processing.
167 if (moves
&& repno
&&
168 (aplist_append(&alp
, (void *)addr
, AL_CNT_MOVES
) == NULL
))
173 * Binaries built in the early 1990's prior to Solaris 8, using the ild
174 * incremental linker are known to have zero filled move sections
175 * (presumably place holders for new, incoming move sections). If no
176 * move records have been processed, remove the move identifier to
177 * optimize the amount of backward compatibility copy relocation
178 * processing that is needed.
180 if (moves
&& (alp
== NULL
))
181 FLAGS(lmp
) &= ~FLG_RT_MOVE
;
187 * Determine whether an address is the recipient of a move record.
188 * Returns 1 if the address matches a move symbol, 0 otherwise.
191 is_move_data(caddr_t addr
)
196 for (APLIST_TRAVERSE(alp
, idx
, maddr
)) {