NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: port-arm/49299: earmv7hfeb kernels can not load modules
The following reply was made to PR port-arm/49299; it has been noted by GNATS.
From: Christos Zoulas <christos%zoulas.com@localhost>
To: "gnats-bugs%NetBSD.org@localhost" <gnats-bugs%NetBSD.org@localhost>
Cc: "port-arm-maintainer%netbsd.org@localhost" <port-arm-maintainer%netbsd.org@localhost>,
"gnats-admin%netbsd.org@localhost" <gnats-admin%netbsd.org@localhost>,
"netbsd-bugs%netbsd.org@localhost" <netbsd-bugs%netbsd.org@localhost>,
"martin%NetBSD.org@localhost" <martin%NetBSD.org@localhost>
Subject: Re: port-arm/49299: earmv7hfeb kernels can not load modules
Date: Thu, 6 Nov 2014 18:49:02 -0500
> + if (ELF_ST_BIND(info) !=3D STB_LOCAL)
> + return Other;
> + if (ELF_ST_TYPE(info) !=3D STT_NOTYPE)
> + return Other;
> + if (strcmp(name, "$a") =3D=3D 0)
> + return ArmStart;
> + if (strncmp(name, "$a.", 3) =3D=3D 0)
> + return ArmStart;
> + if (strcmp(name, "$t") =3D=3D 0)
> + return ThumbStart;
> + if (strncmp(name, "$t.", 3) =3D=3D 0)
> + return ThumbStart;
> + if (strcmp(name, "$d") =3D=3D 0)
> + return DataStart;
> + if (strncmp(name, "$d.", 3) =3D=3D 0)
> + return DataStart;
> + return Other;
> +}
> +
This sequence of strcmps can be made a lot more efficient with specialized c=
ode (and smaller)
> +static int
> +be8_ksym_count(const char *name, int symindex, void *value, uint32_t size=
,
> + int info, void *cookie)
> +{
> + size_t *res =3D cookie;
> + enum be8_magic_sym_type t =3D be8_sym_type(name, info);
> +
> + if (t !=3D Other)
> + (*res)++;
> + return 0;
> +}
> +
> +static int
> +be8_ksym_add(const char *name, int symindex, void *value, uint32_t size,
> + int info, void *cookie)
> +{
> + size_t ndx;
> + struct be8_marker_list *list =3D cookie;
> + enum be8_magic_sym_type t =3D be8_sym_type(name, info);
> +
> + if (t =3D=3D Other)
> + return 0;
> +
> + ndx =3D list->cnt++;
> + list->markers[ndx].type =3D t;
> + list->markers[ndx].addr =3D value;
> +
> + return 0;
> +}
> +
> +static int
> +be8_ksym_comp(const void *a, const void *b)
> +{
> + const struct be8_marker *ma =3D a, *mb =3D b;
> + uintptr_t va =3D (uintptr_t)ma->addr, vb =3D (uintptr_t)mb->addr;
> +
> + if (va =3D=3D vb)
> + return 0;
> + if (va < vb)
> + return -1;
> + return 1;
> +}
> +
> +static void
> +be8_ksym_swap(void *start, size_t size, const struct be8_marker_list *lis=
t)
> +{
> + uintptr_t va_end =3D (uintptr_t)start + size;
> + size_t i;
> + uint32_t *p32, *p32_end, v32;
> + uint16_t *p16, *p16_end, v16;
> +
> + /* find first relevant list entry */
> + for (i =3D 0; i < list->cnt; i++)
> + if (start <=3D list->markers[i].addr)
> + break;
> +
> + /* swap all arm and thumb code parts of this section */
> + for ( ; i < list->cnt; i++) {
> + switch (list->markers[i].type) {
> + case ArmStart:
> + p32 =3D (uint32_t*)list->markers[i].addr;
> + p32_end =3D (uint32_t*)va_end;
> + if (i+1 < list->cnt) {
> + if ((uintptr_t)list->markers[i+1].addr
> + < va_end)
> + p32_end =3D (uint32_t*)
> + list->markers[i+1].addr;
> + }
> + while (p32 < p32_end) {
> + v32 =3D bswap32(*p32);
> + *p32++ =3D v32;
> + }
> + break;
> + case ThumbStart:
> + p16 =3D (uint16_t*)list->markers[i].addr;
> + p16_end =3D (uint16_t*)va_end;
> + if (i+1 < list->cnt) {
> + if ((uintptr_t)list->markers[i+1].addr
> + < va_end)
> + p16_end =3D (uint16_t*)
> + list->markers[i+1].addr;
> + =20
I think a default and break here is better
> }
> + while (p16 < p16_end) {
> + v16 =3D bswap16(*p16);
> + *p16++ =3D v16;
> + }
> + break;
> + default:
> + break;
> + }
> + }
> +}
> +=20
> +static void
> +kobj_be8_fixup(kobj_t ko)
> +{
> + size_t relsym_cnt =3D 0, i;
> + struct be8_marker_list list;
> + struct be8_marker tmp;
> +
> + /*
> + * Count all special relocations symbols
> + */
> + ksyms_mod_foreach(ko->ko_name, be8_ksym_count, &relsym_cnt);
> +
> + /*
> + * Provide storage for the address list and add the symbols
> + */
> + list.cnt =3D 0;
> + list.markers =3D kmem_alloc(relsym_cnt*sizeof(*list.markers), KM_SLEE=
P);
> + ksyms_mod_foreach(ko->ko_name, be8_ksym_add, &list);
> + KASSERT(list.cnt =3D=3D relsym_cnt);
> +
> + /*
> + * Sort symbols by ascending address
> + */
> + if (kheapsort(list.markers, relsym_cnt, sizeof(*list.markers),
> + be8_ksym_comp, &tmp) !=3D 0)
> + panic("could not sort be8 marker symbols");
> +
> + /*
> + * Apply swaps to the .text section (XXX we do not have the
> + * section header available any more, it has been jetisoned
> + * already, so we can not check for all PROGBIT sections).
> + */
> + for (i =3D 0; i < ko->ko_nprogtab; i++) {
> + if (strcmp(ko->ko_progtab[i].name, ".text") !=3D 0)
> + continue;
> + be8_ksym_swap(ko->ko_progtab[i].addr,
> + (size_t)ko->ko_progtab[i].size,
> + &list);
> + }
> +
> + /*
> + * Done, free list
> + */
> + kmem_free(list.markers, relsym_cnt*sizeof(*list.markers));
> +}
> +#endif
> +
> int
> kobj_machdep(kobj_t ko, void *base, size_t size, bool load)
> {
> @@ -212,6 +400,9 @@ kobj_machdep(kobj_t ko, void *base, size
> cpu_idcache_wbinv_range((vaddr_t)base, size);
> cpu_tlb_flushID();
> #endif
> +#ifdef ARM_8EB
> + kobj_be8_fixup(ko);
> +#endif
> }
>=20
> return 0;
>=20
> --5mCyUwZo2JvN/JJP--
>=20
Home |
Main Index |
Thread Index |
Old Index