aboutsummaryrefslogtreecommitdiff
path: root/elf/dl-find_object.h
diff options
context:
space:
mode:
Diffstat (limited to 'elf/dl-find_object.h')
-rw-r--r--elf/dl-find_object.h57
1 files changed, 43 insertions, 14 deletions
diff --git a/elf/dl-find_object.h b/elf/dl-find_object.h
index e433ff8..d9d75c4 100644
--- a/elf/dl-find_object.h
+++ b/elf/dl-find_object.h
@@ -43,6 +43,7 @@ struct dl_find_object_internal
#if DLFO_STRUCT_HAS_EH_COUNT
int eh_count;
#endif
+ void *sframe;
};
/* Create a copy of *SOURCE in *COPY using relaxed MO loads and
@@ -67,13 +68,14 @@ _dl_find_object_internal_copy (const struct dl_find_object_internal *source,
atomic_store_relaxed (&copy->eh_count,
atomic_load_relaxed (&source->eh_count));
#endif
+ atomic_store_relaxed (&copy->sframe,
+ atomic_load_relaxed (&source->sframe));
}
static inline void
_dl_find_object_to_external (struct dl_find_object_internal *internal,
struct dl_find_object *external)
{
- external->dlfo_flags = 0;
external->dlfo_map_start = (void *) internal->map_start;
external->dlfo_map_end = (void *) internal->map_end;
external->dlfo_link_map = internal->map;
@@ -84,14 +86,22 @@ _dl_find_object_to_external (struct dl_find_object_internal *internal,
# if DLFO_STRUCT_HAS_EH_COUNT
external->dlfo_eh_count = internal->eh_count;
# endif
+ external->dlfo_sframe = internal->sframe;
+ if (internal->sframe != NULL)
+ external->dlfo_flags = DLFO_FLAG_SFRAME;
+ else
+ external->dlfo_flags = 0;
}
/* Extract the object location data from a link map and writes it to
- *RESULT using relaxed MO stores. */
+ *RESULT using relaxed MO stores. Set L->l_find_object_processed. */
static void __attribute__ ((unused))
_dl_find_object_from_map (struct link_map *l,
struct dl_find_object_internal *result)
{
+ /* A mask to find out which segment has been read out. */
+ unsigned int read_seg = 0;
+
atomic_store_relaxed (&result->map_start, (uintptr_t) l->l_map_start);
atomic_store_relaxed (&result->map_end, (uintptr_t) l->l_map_end);
atomic_store_relaxed (&result->map, l);
@@ -100,23 +110,42 @@ _dl_find_object_from_map (struct link_map *l,
atomic_store_relaxed (&result->eh_dbase, (void *) l->l_info[DT_PLTGOT]);
#endif
- for (const ElfW(Phdr) *ph = l->l_phdr, *ph_end = l->l_phdr + l->l_phnum;
- ph < ph_end; ++ph)
- if (ph->p_type == DLFO_EH_SEGMENT_TYPE)
- {
- atomic_store_relaxed (&result->eh_frame,
- (void *) (ph->p_vaddr + l->l_addr));
+ /* Initialize object's exception handling segment and SFrame segment
+ data. */
+ atomic_store_relaxed (&result->sframe, NULL);
+ atomic_store_relaxed (&result->eh_frame, NULL);
#if DLFO_STRUCT_HAS_EH_COUNT
- atomic_store_relaxed (&result->eh_count, ph->p_memsz / 8);
+ atomic_store_relaxed (&result->eh_count, 0);
#endif
- return;
- }
- /* Object has no exception handling segment. */
- atomic_store_relaxed (&result->eh_frame, NULL);
+ for (const ElfW(Phdr) *ph = l->l_phdr, *ph_end = l->l_phdr + l->l_phnum;
+ ph < ph_end; ++ph)
+ {
+ switch (ph->p_type)
+ {
+ case DLFO_EH_SEGMENT_TYPE:
+ atomic_store_relaxed (&result->eh_frame,
+ (void *) (ph->p_vaddr + l->l_addr));
#if DLFO_STRUCT_HAS_EH_COUNT
- atomic_store_relaxed (&result->eh_count, 0);
+ atomic_store_relaxed (&result->eh_count, ph->p_memsz / 8);
#endif
+ read_seg |= 1;
+ break;
+
+ case PT_GNU_SFRAME:
+ atomic_store_relaxed (&result->sframe,
+ (void *) (ph->p_vaddr + l->l_addr));
+ read_seg |= 2;
+ /* Fall through. */
+ default:
+ break;
+ }
+ if (read_seg == 3)
+ goto done;
+ }
+
+ done:
+ l->l_find_object_processed = 1;
}
/* Called by the dynamic linker to set up the data structures for the