mirror of git://sourceware.org/git/glibc.git
Update.
2004-02-29 Paolo Bonzini <bonzini@gnu.org> * posix/regexec.c (transit_state): Don't handle state == NULL. Move state log and backreference management... (merge_state_with_log): ... to this function. (find_recover_state): New function. (check_matching): Use find_recover_state to get a non-NULL state when an invalid state is reached. Compute the amount of initial characters to be skipped less conservatively when multi-byte character sets are in use. Do not check dfa->nbackref if the state log is NULL. Initialize err. (acquire_init_state_context): Expect err to be initialized. Fix spacing. 2004-03-05 Jakub Jelinek <jakub@redhat.com> * sysdeps/sparc/sparc32/elf/start.S: Handle PIEs. * sysdeps/sparc/sparc64/elf/start.S: Likewise.
This commit is contained in:
parent
f2fcb018ad
commit
4c595adb60
19
ChangeLog
19
ChangeLog
|
@ -1,3 +1,22 @@
|
||||||
|
2004-02-29 Paolo Bonzini <bonzini@gnu.org>
|
||||||
|
|
||||||
|
* posix/regexec.c (transit_state): Don't handle state == NULL.
|
||||||
|
Move state log and backreference management...
|
||||||
|
(merge_state_with_log): ... to this function.
|
||||||
|
(find_recover_state): New function.
|
||||||
|
(check_matching): Use find_recover_state to get a non-NULL
|
||||||
|
state when an invalid state is reached. Compute the amount
|
||||||
|
of initial characters to be skipped less conservatively when
|
||||||
|
multi-byte character sets are in use. Do not check
|
||||||
|
dfa->nbackref if the state log is NULL. Initialize err.
|
||||||
|
(acquire_init_state_context): Expect err to be initialized.
|
||||||
|
Fix spacing.
|
||||||
|
|
||||||
|
2004-03-05 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
|
* sysdeps/sparc/sparc32/elf/start.S: Handle PIEs.
|
||||||
|
* sysdeps/sparc/sparc64/elf/start.S: Likewise.
|
||||||
|
|
||||||
2004-03-04 Jakub Jelinek <jakub@redhat.com>
|
2004-03-04 Jakub Jelinek <jakub@redhat.com>
|
||||||
|
|
||||||
* iconv/iconv_prog.c (process_block): Handle omit_invalid.
|
* iconv/iconv_prog.c (process_block): Handle omit_invalid.
|
||||||
|
|
303
posix/regexec.c
303
posix/regexec.c
|
@ -123,9 +123,14 @@ static reg_errcode_t clean_state_log_if_needed (re_match_context_t *mctx,
|
||||||
int next_state_log_idx) internal_function;
|
int next_state_log_idx) internal_function;
|
||||||
static reg_errcode_t merge_state_array (re_dfa_t *dfa, re_dfastate_t **dst,
|
static reg_errcode_t merge_state_array (re_dfa_t *dfa, re_dfastate_t **dst,
|
||||||
re_dfastate_t **src, int num) internal_function;
|
re_dfastate_t **src, int num) internal_function;
|
||||||
|
static re_dfastate_t *find_recover_state (reg_errcode_t *err,
|
||||||
|
re_match_context_t *mctx) internal_function;
|
||||||
static re_dfastate_t *transit_state (reg_errcode_t *err,
|
static re_dfastate_t *transit_state (reg_errcode_t *err,
|
||||||
re_match_context_t *mctx,
|
re_match_context_t *mctx,
|
||||||
re_dfastate_t *state) internal_function;
|
re_dfastate_t *state) internal_function;
|
||||||
|
static re_dfastate_t *merge_state_with_log (reg_errcode_t *err,
|
||||||
|
re_match_context_t *mctx,
|
||||||
|
re_dfastate_t *next_state) internal_function;
|
||||||
static reg_errcode_t check_subexp_matching_top (re_match_context_t *mctx,
|
static reg_errcode_t check_subexp_matching_top (re_match_context_t *mctx,
|
||||||
re_node_set *cur_nodes,
|
re_node_set *cur_nodes,
|
||||||
int str_idx) internal_function;
|
int str_idx) internal_function;
|
||||||
|
@ -936,7 +941,6 @@ acquire_init_state_context (err, mctx, idx)
|
||||||
int idx;
|
int idx;
|
||||||
{
|
{
|
||||||
re_dfa_t *const dfa = mctx->dfa;
|
re_dfa_t *const dfa = mctx->dfa;
|
||||||
*err = REG_NOERROR;
|
|
||||||
if (dfa->init_state->has_constraint)
|
if (dfa->init_state->has_constraint)
|
||||||
{
|
{
|
||||||
unsigned int context;
|
unsigned int context;
|
||||||
|
@ -952,9 +956,9 @@ acquire_init_state_context (err, mctx, idx)
|
||||||
else if (IS_BEGBUF_CONTEXT (context))
|
else if (IS_BEGBUF_CONTEXT (context))
|
||||||
{
|
{
|
||||||
/* It is relatively rare case, then calculate on demand. */
|
/* It is relatively rare case, then calculate on demand. */
|
||||||
return re_acquire_state_context (err, dfa,
|
return re_acquire_state_context (err, dfa,
|
||||||
dfa->init_state->entrance_nodes,
|
dfa->init_state->entrance_nodes,
|
||||||
context);
|
context);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
/* Must not happen? */
|
/* Must not happen? */
|
||||||
|
@ -985,29 +989,37 @@ check_matching (mctx, fl_longest_match, p_match_first)
|
||||||
int match_last = -1;
|
int match_last = -1;
|
||||||
int cur_str_idx = re_string_cur_idx (&mctx->input);
|
int cur_str_idx = re_string_cur_idx (&mctx->input);
|
||||||
re_dfastate_t *cur_state;
|
re_dfastate_t *cur_state;
|
||||||
int at_init_state = p_match_first != NULL, skipped = 0;
|
int at_init_state = p_match_first != NULL;
|
||||||
|
int next_start_idx = cur_str_idx;
|
||||||
|
|
||||||
|
err = REG_NOERROR;
|
||||||
cur_state = acquire_init_state_context (&err, mctx, cur_str_idx);
|
cur_state = acquire_init_state_context (&err, mctx, cur_str_idx);
|
||||||
/* An initial state must not be NULL(invalid state). */
|
/* An initial state must not be NULL (invalid). */
|
||||||
if (BE (cur_state == NULL, 0))
|
if (BE (cur_state == NULL, 0))
|
||||||
return -2;
|
|
||||||
if (mctx->state_log != NULL)
|
|
||||||
mctx->state_log[cur_str_idx] = cur_state;
|
|
||||||
|
|
||||||
/* Check OP_OPEN_SUBEXP in the initial state in case that we use them
|
|
||||||
later. E.g. Processing back references. */
|
|
||||||
if (BE (dfa->nbackref, 0))
|
|
||||||
{
|
{
|
||||||
at_init_state = 0;
|
assert (err == REG_ESPACE);
|
||||||
err = check_subexp_matching_top (mctx, &cur_state->nodes, 0);
|
return -2;
|
||||||
if (BE (err != REG_NOERROR, 0))
|
}
|
||||||
return err;
|
|
||||||
|
|
||||||
if (cur_state->has_backref)
|
if (mctx->state_log != NULL)
|
||||||
|
{
|
||||||
|
mctx->state_log[cur_str_idx] = cur_state;
|
||||||
|
|
||||||
|
/* Check OP_OPEN_SUBEXP in the initial state in case that we use them
|
||||||
|
later. E.g. Processing back references. */
|
||||||
|
if (BE (dfa->nbackref, 0))
|
||||||
{
|
{
|
||||||
err = transit_state_bkref (mctx, &cur_state->nodes);
|
at_init_state = 0;
|
||||||
|
err = check_subexp_matching_top (mctx, &cur_state->nodes, 0);
|
||||||
if (BE (err != REG_NOERROR, 0))
|
if (BE (err != REG_NOERROR, 0))
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
if (cur_state->has_backref)
|
||||||
|
{
|
||||||
|
err = transit_state_bkref (mctx, &cur_state->nodes);
|
||||||
|
if (BE (err != REG_NOERROR, 0))
|
||||||
|
return err;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1031,40 +1043,34 @@ check_matching (mctx, fl_longest_match, p_match_first)
|
||||||
{
|
{
|
||||||
re_dfastate_t *old_state = cur_state;
|
re_dfastate_t *old_state = cur_state;
|
||||||
cur_state = transit_state (&err, mctx, cur_state);
|
cur_state = transit_state (&err, mctx, cur_state);
|
||||||
|
if (mctx->state_log != NULL)
|
||||||
|
cur_state = merge_state_with_log (&err, mctx, cur_state);
|
||||||
|
|
||||||
|
if (cur_state == NULL)
|
||||||
|
{
|
||||||
|
/* Reached the invalid state or an error. Try to recover a valid
|
||||||
|
state using the state log, if available and if we have not
|
||||||
|
already found a valid (even if not the longest) match. */
|
||||||
|
if (BE (err != REG_NOERROR, 0))
|
||||||
|
return -2;
|
||||||
|
|
||||||
|
if (mctx->state_log == NULL
|
||||||
|
|| (match && !fl_longest_match)
|
||||||
|
|| (cur_state = find_recover_state (&err, mctx)) == NULL)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (at_init_state)
|
if (at_init_state)
|
||||||
{
|
{
|
||||||
if (old_state == cur_state)
|
if (old_state == cur_state)
|
||||||
skipped++;
|
next_start_idx = re_string_cur_idx (&mctx->input);
|
||||||
else
|
else
|
||||||
at_init_state = 0;
|
at_init_state = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cur_state == NULL) /* Reached at the invalid state or an error. */
|
if (cur_state->halt)
|
||||||
{
|
{
|
||||||
cur_str_idx = re_string_cur_idx (&mctx->input);
|
/* Reached a halt state.
|
||||||
if (BE (err != REG_NOERROR, 0))
|
|
||||||
return -2;
|
|
||||||
if (!fl_longest_match && match)
|
|
||||||
break;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (mctx->state_log == NULL)
|
|
||||||
break;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int max = mctx->state_log_top;
|
|
||||||
for (; cur_str_idx <= max; ++cur_str_idx)
|
|
||||||
if (mctx->state_log[cur_str_idx] != NULL)
|
|
||||||
break;
|
|
||||||
if (cur_str_idx > max)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cur_state != NULL && cur_state->halt)
|
|
||||||
{
|
|
||||||
/* Reached at a halt state.
|
|
||||||
Check the halt state can satisfy the current context. */
|
Check the halt state can satisfy the current context. */
|
||||||
if (!cur_state->has_constraint
|
if (!cur_state->has_constraint
|
||||||
|| check_halt_state_context (mctx, cur_state,
|
|| check_halt_state_context (mctx, cur_state,
|
||||||
|
@ -1079,8 +1085,8 @@ check_matching (mctx, fl_longest_match, p_match_first)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (match_last == -1 && skipped)
|
if (match_last == -1 && p_match_first)
|
||||||
*p_match_first += skipped;
|
*p_match_first += next_start_idx;
|
||||||
|
|
||||||
return match_last;
|
return match_last;
|
||||||
}
|
}
|
||||||
|
@ -2134,7 +2140,6 @@ transit_state (err, mctx, state)
|
||||||
re_dfa_t *const dfa = mctx->dfa;
|
re_dfa_t *const dfa = mctx->dfa;
|
||||||
re_dfastate_t **trtable, *next_state;
|
re_dfastate_t **trtable, *next_state;
|
||||||
unsigned char ch;
|
unsigned char ch;
|
||||||
int cur_idx;
|
|
||||||
|
|
||||||
if (re_string_cur_idx (&mctx->input) + 1 >= mctx->input.bufs_len
|
if (re_string_cur_idx (&mctx->input) + 1 >= mctx->input.bufs_len
|
||||||
|| (re_string_cur_idx (&mctx->input) + 1 >= mctx->input.valid_len
|
|| (re_string_cur_idx (&mctx->input) + 1 >= mctx->input.valid_len
|
||||||
|
@ -2145,14 +2150,6 @@ transit_state (err, mctx, state)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
*err = REG_NOERROR;
|
|
||||||
if (state == NULL)
|
|
||||||
{
|
|
||||||
next_state = state;
|
|
||||||
re_string_skip_bytes (&mctx->input, 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
#ifdef RE_ENABLE_I18N
|
#ifdef RE_ENABLE_I18N
|
||||||
/* If the current state can accept multibyte. */
|
/* If the current state can accept multibyte. */
|
||||||
if (state->accept_mb)
|
if (state->accept_mb)
|
||||||
|
@ -2163,95 +2160,96 @@ transit_state (err, mctx, state)
|
||||||
}
|
}
|
||||||
#endif /* RE_ENABLE_I18N */
|
#endif /* RE_ENABLE_I18N */
|
||||||
|
|
||||||
/* Then decide the next state with the single byte. */
|
/* Then decide the next state with the single byte. */
|
||||||
if (1)
|
if (1)
|
||||||
{
|
|
||||||
/* Use transition table */
|
|
||||||
ch = re_string_fetch_byte (&mctx->input);
|
|
||||||
trtable = state->trtable;
|
|
||||||
if (trtable == NULL)
|
|
||||||
{
|
|
||||||
trtable = build_trtable (dfa, state);
|
|
||||||
if (trtable == NULL)
|
|
||||||
{
|
|
||||||
*err = REG_ESPACE;
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (BE (state->word_trtable, 0))
|
|
||||||
{
|
|
||||||
unsigned int context;
|
|
||||||
context
|
|
||||||
= re_string_context_at (&mctx->input,
|
|
||||||
re_string_cur_idx (&mctx->input) - 1,
|
|
||||||
mctx->eflags);
|
|
||||||
if (IS_WORD_CONTEXT (context))
|
|
||||||
next_state = trtable[ch + SBC_MAX];
|
|
||||||
else
|
|
||||||
next_state = trtable[ch];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
next_state = trtable[ch];
|
|
||||||
}
|
|
||||||
#if 0
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/* don't use transition table */
|
|
||||||
next_state = transit_state_sb (err, mctx, state);
|
|
||||||
if (BE (next_state == NULL && *err != REG_NOERROR, 0))
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
cur_idx = re_string_cur_idx (&mctx->input);
|
|
||||||
/* Update the state_log if we need. */
|
|
||||||
if (mctx->state_log != NULL)
|
|
||||||
{
|
{
|
||||||
if (cur_idx > mctx->state_log_top)
|
/* Use transition table */
|
||||||
{
|
ch = re_string_fetch_byte (&mctx->input);
|
||||||
mctx->state_log[cur_idx] = next_state;
|
trtable = state->trtable;
|
||||||
mctx->state_log_top = cur_idx;
|
if (trtable == NULL)
|
||||||
|
{
|
||||||
|
trtable = build_trtable (dfa, state);
|
||||||
|
if (trtable == NULL)
|
||||||
|
{
|
||||||
|
*err = REG_ESPACE;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (mctx->state_log[cur_idx] == 0)
|
if (BE (state->word_trtable, 0))
|
||||||
{
|
{
|
||||||
mctx->state_log[cur_idx] = next_state;
|
unsigned int context;
|
||||||
|
context
|
||||||
|
= re_string_context_at (&mctx->input,
|
||||||
|
re_string_cur_idx (&mctx->input) - 1,
|
||||||
|
mctx->eflags);
|
||||||
|
if (IS_WORD_CONTEXT (context))
|
||||||
|
return trtable[ch + SBC_MAX];
|
||||||
|
else
|
||||||
|
return trtable[ch];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
return trtable[ch];
|
||||||
re_dfastate_t *pstate;
|
}
|
||||||
unsigned int context;
|
#if 0
|
||||||
re_node_set next_nodes, *log_nodes, *table_nodes = NULL;
|
else
|
||||||
/* If (state_log[cur_idx] != 0), it implies that cur_idx is
|
/* don't use transition table */
|
||||||
the destination of a multibyte char/collating element/
|
return transit_state_sb (err, mctx, state);
|
||||||
back reference. Then the next state is the union set of
|
#endif
|
||||||
these destinations and the results of the transition table. */
|
}
|
||||||
pstate = mctx->state_log[cur_idx];
|
|
||||||
log_nodes = pstate->entrance_nodes;
|
/* Update the state_log if we need */
|
||||||
if (next_state != NULL)
|
re_dfastate_t *
|
||||||
{
|
merge_state_with_log (err, mctx, next_state)
|
||||||
table_nodes = next_state->entrance_nodes;
|
reg_errcode_t *err;
|
||||||
*err = re_node_set_init_union (&next_nodes, table_nodes,
|
re_match_context_t *mctx;
|
||||||
|
re_dfastate_t *next_state;
|
||||||
|
{
|
||||||
|
re_dfa_t *const dfa = mctx->dfa;
|
||||||
|
int cur_idx = re_string_cur_idx (&mctx->input);
|
||||||
|
|
||||||
|
if (cur_idx > mctx->state_log_top)
|
||||||
|
{
|
||||||
|
mctx->state_log[cur_idx] = next_state;
|
||||||
|
mctx->state_log_top = cur_idx;
|
||||||
|
}
|
||||||
|
else if (mctx->state_log[cur_idx] == 0)
|
||||||
|
{
|
||||||
|
mctx->state_log[cur_idx] = next_state;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
re_dfastate_t *pstate;
|
||||||
|
unsigned int context;
|
||||||
|
re_node_set next_nodes, *log_nodes, *table_nodes = NULL;
|
||||||
|
/* If (state_log[cur_idx] != 0), it implies that cur_idx is
|
||||||
|
the destination of a multibyte char/collating element/
|
||||||
|
back reference. Then the next state is the union set of
|
||||||
|
these destinations and the results of the transition table. */
|
||||||
|
pstate = mctx->state_log[cur_idx];
|
||||||
|
log_nodes = pstate->entrance_nodes;
|
||||||
|
if (next_state != NULL)
|
||||||
|
{
|
||||||
|
table_nodes = next_state->entrance_nodes;
|
||||||
|
*err = re_node_set_init_union (&next_nodes, table_nodes,
|
||||||
log_nodes);
|
log_nodes);
|
||||||
if (BE (*err != REG_NOERROR, 0))
|
if (BE (*err != REG_NOERROR, 0))
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
next_nodes = *log_nodes;
|
next_nodes = *log_nodes;
|
||||||
/* Note: We already add the nodes of the initial state,
|
/* Note: We already add the nodes of the initial state,
|
||||||
then we don't need to add them here. */
|
then we don't need to add them here. */
|
||||||
|
|
||||||
context = re_string_context_at (&mctx->input,
|
context = re_string_context_at (&mctx->input,
|
||||||
re_string_cur_idx (&mctx->input) - 1,
|
re_string_cur_idx (&mctx->input) - 1,
|
||||||
mctx->eflags);
|
mctx->eflags);
|
||||||
next_state = mctx->state_log[cur_idx]
|
next_state = mctx->state_log[cur_idx]
|
||||||
= re_acquire_state_context (err, dfa, &next_nodes, context);
|
= re_acquire_state_context (err, dfa, &next_nodes, context);
|
||||||
/* We don't need to check errors here, since the return value of
|
/* We don't need to check errors here, since the return value of
|
||||||
this function is next_state and ERR is already set. */
|
this function is next_state and ERR is already set. */
|
||||||
|
|
||||||
if (table_nodes != NULL)
|
if (table_nodes != NULL)
|
||||||
re_node_set_free (&next_nodes);
|
re_node_set_free (&next_nodes);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (BE (dfa->nbackref, 0) && next_state != NULL)
|
if (BE (dfa->nbackref, 0) && next_state != NULL)
|
||||||
|
@ -2273,9 +2271,38 @@ transit_state (err, mctx, state)
|
||||||
next_state = mctx->state_log[cur_idx];
|
next_state = mctx->state_log[cur_idx];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return next_state;
|
return next_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Skip bytes in the input that correspond to part of a
|
||||||
|
multi-byte match, then look in the log for a state
|
||||||
|
from which to restart matching. */
|
||||||
|
re_dfastate_t *
|
||||||
|
find_recover_state (err, mctx)
|
||||||
|
reg_errcode_t *err;
|
||||||
|
re_match_context_t *mctx;
|
||||||
|
{
|
||||||
|
re_dfastate_t *cur_state = NULL;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
int max = mctx->state_log_top;
|
||||||
|
int cur_str_idx = re_string_cur_idx (&mctx->input);
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (++cur_str_idx > max)
|
||||||
|
return NULL;
|
||||||
|
re_string_skip_bytes (&mctx->input, 1);
|
||||||
|
}
|
||||||
|
while (mctx->state_log[cur_str_idx] == NULL);
|
||||||
|
|
||||||
|
cur_state = merge_state_with_log (err, mctx, NULL);
|
||||||
|
}
|
||||||
|
while (err == REG_NOERROR && cur_state == NULL);
|
||||||
|
return cur_state;
|
||||||
|
}
|
||||||
|
|
||||||
/* Helper functions for transit_state. */
|
/* Helper functions for transit_state. */
|
||||||
|
|
||||||
/* From the node set CUR_NODES, pick up the nodes whose types are
|
/* From the node set CUR_NODES, pick up the nodes whose types are
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* Startup code for elf32-sparc
|
/* Startup code for elf32-sparc
|
||||||
Copyright (C) 1997, 1998, 2002 Free Software Foundation, Inc.
|
Copyright (C) 1997, 1998, 2002, 2004 Free Software Foundation, Inc.
|
||||||
This file is part of the GNU C Library.
|
This file is part of the GNU C Library.
|
||||||
Contributed by Richard Henderson <richard@gnu.ai.mit.edu>, 1997.
|
Contributed by Richard Henderson <richard@gnu.ai.mit.edu>, 1997.
|
||||||
|
|
||||||
|
@ -23,10 +23,21 @@
|
||||||
|
|
||||||
.section ".text"
|
.section ".text"
|
||||||
.align 4
|
.align 4
|
||||||
|
#ifdef SHARED
|
||||||
|
.LLGETPC0:
|
||||||
|
retl
|
||||||
|
add %o7, %l7, %l7
|
||||||
|
#endif
|
||||||
.global _start
|
.global _start
|
||||||
.type _start,#function
|
.type _start,#function
|
||||||
_start:
|
_start:
|
||||||
|
|
||||||
|
#ifdef SHARED
|
||||||
|
sethi %hi(_GLOBAL_OFFSET_TABLE_-4), %l7
|
||||||
|
call .LLGETPC0
|
||||||
|
add %l7, %lo(_GLOBAL_OFFSET_TABLE_+4), %l7
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Terminate the stack frame, and reserve space for functions to
|
/* Terminate the stack frame, and reserve space for functions to
|
||||||
drop their arguments. */
|
drop their arguments. */
|
||||||
mov %g0, %fp
|
mov %g0, %fp
|
||||||
|
@ -44,6 +55,11 @@ _start:
|
||||||
or %o0, %lo(main), %o0
|
or %o0, %lo(main), %o0
|
||||||
or %o3, %lo(__libc_csu_init), %o3
|
or %o3, %lo(__libc_csu_init), %o3
|
||||||
or %o4, %lo(__libc_csu_fini), %o4
|
or %o4, %lo(__libc_csu_fini), %o4
|
||||||
|
#ifdef SHARED
|
||||||
|
ld [%l7 + %o0], %o0
|
||||||
|
ld [%l7 + %o3], %o3
|
||||||
|
ld [%l7 + %o4], %o4
|
||||||
|
#endif
|
||||||
|
|
||||||
/* When starting a binary via the dynamic linker, %g1 contains the
|
/* When starting a binary via the dynamic linker, %g1 contains the
|
||||||
address of the shared library termination function, which will be
|
address of the shared library termination function, which will be
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* Startup code for elf64-sparc
|
/* Startup code for elf64-sparc
|
||||||
Copyright (C) 1997, 1998, 2002 Free Software Foundation, Inc.
|
Copyright (C) 1997, 1998, 2002, 2004 Free Software Foundation, Inc.
|
||||||
This file is part of the GNU C Library.
|
This file is part of the GNU C Library.
|
||||||
Contributed by Richard Henderson <richard@gnu.ai.mit.edu>, 1997.
|
Contributed by Richard Henderson <richard@gnu.ai.mit.edu>, 1997.
|
||||||
|
|
||||||
|
@ -23,10 +23,21 @@
|
||||||
|
|
||||||
.section ".text"
|
.section ".text"
|
||||||
.align 4
|
.align 4
|
||||||
|
#ifdef SHARED
|
||||||
|
.LLGETPC0:
|
||||||
|
retl
|
||||||
|
add %o7, %l7, %l7
|
||||||
|
#endif
|
||||||
.global _start
|
.global _start
|
||||||
.type _start,#function
|
.type _start,#function
|
||||||
_start:
|
_start:
|
||||||
|
|
||||||
|
#ifdef SHARED
|
||||||
|
sethi %hi(_GLOBAL_OFFSET_TABLE_-4), %l7
|
||||||
|
call .LLGETPC0
|
||||||
|
add %l7, %lo(_GLOBAL_OFFSET_TABLE_+4), %l7
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Terminate the stack frame, and reserve space for functions to
|
/* Terminate the stack frame, and reserve space for functions to
|
||||||
drop their arguments. */
|
drop their arguments. */
|
||||||
mov %g0, %fp
|
mov %g0, %fp
|
||||||
|
@ -45,6 +56,11 @@ _start:
|
||||||
or %o0, %lo(main), %o0
|
or %o0, %lo(main), %o0
|
||||||
or %o3, %lo(__libc_csu_init), %o3
|
or %o3, %lo(__libc_csu_init), %o3
|
||||||
or %o4, %lo(__libc_csu_fini), %o4
|
or %o4, %lo(__libc_csu_fini), %o4
|
||||||
|
#ifdef SHARED
|
||||||
|
ldx [%l7 + %o0], %o0
|
||||||
|
ldx [%l7 + %o3], %o3
|
||||||
|
ldx [%l7 + %o4], %o4
|
||||||
|
#endif
|
||||||
|
|
||||||
/* When starting a binary via the dynamic linker, %g1 contains the
|
/* When starting a binary via the dynamic linker, %g1 contains the
|
||||||
address of the shared library termination function, which will be
|
address of the shared library termination function, which will be
|
||||||
|
|
Loading…
Reference in New Issue