mirror of
https://github.com/apache/nuttx.git
synced 2026-08-21 05:28:19 +00:00
Implement architecture-specific ELF header definitions and relocation handling for the MIPS architecture to enable loadable modules. Fixes #19178. Changes include: - Add `arch/mips/include/elf.h` with MIPS ELF relocation types and architecture-specific ELF data structures (`arch_elfdata_s`). - Implement `libs/libc/machine/mips/arch_elf.c` containing `up_checkarch`, `up_relocate`, and `up_relocateadd` functions handling `R_MIPS_NONE`, `R_MIPS_32`, `R_MIPS_26`, `R_MIPS_HI16`, and `R_MIPS_LO16` relocations. - Integrate MIPS machine-specific C library support in `libs/libc/machine/mips/Make.defs`. - Update `LDMODULEFLAGS` in `arch/mips/src/mips32/Toolchain.defs` to include the little-endian (`-EL`) flag. - Update `up_coherent_dcache` for proper cache synchronization on JZ4780. Signed-off-by: Lwazi Dube <lwazeh@gmail.com>
212 lines
6 KiB
C
212 lines
6 KiB
C
/****************************************************************************
|
|
* libs/libc/machine/mips/arch_elf.c
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership. The
|
|
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
|
* "License"); you may not use this file except in compliance with the
|
|
* License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
|
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
|
* License for the specific language governing permissions and limitations
|
|
* under the License.
|
|
*
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Included Files
|
|
****************************************************************************/
|
|
|
|
#include <nuttx/config.h>
|
|
|
|
#include <inttypes.h>
|
|
#include <stdlib.h>
|
|
#include <errno.h>
|
|
#include <nuttx/debug.h>
|
|
#include <assert.h>
|
|
|
|
#include <nuttx/elf.h>
|
|
|
|
/****************************************************************************
|
|
* Public Functions
|
|
****************************************************************************/
|
|
|
|
/****************************************************************************
|
|
* Name: up_checkarch
|
|
*
|
|
* Description:
|
|
* Given the ELF header in 'hdr', verify that the ELF file is appropriate
|
|
* for the current, configured architecture. Every architecture that uses
|
|
* the ELF loader must provide this function.
|
|
*
|
|
* Input Parameters:
|
|
* hdr - The ELF header read from the ELF file.
|
|
*
|
|
* Returned Value:
|
|
* True if the architecture supports this ELF file.
|
|
*
|
|
****************************************************************************/
|
|
|
|
bool up_checkarch(const Elf32_Ehdr *ehdr)
|
|
{
|
|
/* Make sure it's a MIPS executable */
|
|
|
|
if (ehdr->e_machine != EM_MIPS)
|
|
{
|
|
berr("ERROR: Not for MIPS: e_machine=%04x\n", ehdr->e_machine);
|
|
return false;
|
|
}
|
|
|
|
/* Make sure that 32-bit objects are supported */
|
|
|
|
if (ehdr->e_ident[EI_CLASS] != ELFCLASS32)
|
|
{
|
|
berr("ERROR: Need 32-bit objects: e_ident[EI_CLASS]=%02x\n",
|
|
ehdr->e_ident[EI_CLASS]);
|
|
return false;
|
|
}
|
|
|
|
/* Verify endian-ness */
|
|
|
|
#ifdef CONFIG_ENDIAN_BIG
|
|
if (ehdr->e_ident[EI_DATA] != ELFDATA2MSB)
|
|
#else
|
|
if (ehdr->e_ident[EI_DATA] != ELFDATA2LSB)
|
|
#endif
|
|
{
|
|
berr("ERROR: Wrong endian-ness: e_ident[EI_DATA]=%02x\n",
|
|
ehdr->e_ident[EI_DATA]);
|
|
return false;
|
|
}
|
|
|
|
/* Make sure the entry point address is properly aligned */
|
|
|
|
if ((ehdr->e_entry & 3) != 0)
|
|
{
|
|
berr("ERROR: Entry point is not properly aligned: %08" PRIx32 "\n",
|
|
ehdr->e_entry);
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/****************************************************************************
|
|
* Name: up_relocate and up_relocateadd
|
|
*
|
|
* Description:
|
|
* Perform an architecture-specific ELF relocation. Every architecture
|
|
* that uses the ELF loader must provide this function.
|
|
*
|
|
* Input Parameters:
|
|
* rel - The relocation type
|
|
* sym - The ELF symbol structure containing the fully resolved
|
|
* value. There are a few relocation types for a few
|
|
* architectures that do not require symbol information.
|
|
* For those, this value will be NULL. Implementations of
|
|
* these functions must be able to handle that case.
|
|
* addr - The address that requires the relocation.
|
|
* arch_data - Pointer to architecture specific elf data container.
|
|
*
|
|
* Returned Value:
|
|
* Zero (OK) if the relocation was successful. Otherwise, a negated errno
|
|
* value indicating the cause of the relocation failure.
|
|
*
|
|
****************************************************************************/
|
|
|
|
int up_relocate(const Elf_Rel *rel, const Elf_Sym *sym, uintptr_t addr,
|
|
void *arch_data)
|
|
{
|
|
/* Variable names correspond to the MIPS ABI specification symbols
|
|
* (A, AHI, AHL, P, S) in lowercase.
|
|
*/
|
|
|
|
Elf32_Addr *p = (Elf32_Addr *)addr;
|
|
Elf_Word r_type = ELF_R_TYPE(rel->r_info);
|
|
Elf_Addr s = (sym != NULL) ? sym->st_value : 0;
|
|
arch_elfdata_t *data = (arch_elfdata_t *)arch_data;
|
|
|
|
if ((sym == NULL && r_type != R_MIPS_NONE) || !data)
|
|
{
|
|
return -EINVAL;
|
|
}
|
|
|
|
switch (r_type)
|
|
{
|
|
case R_MIPS_NONE:
|
|
break;
|
|
|
|
case R_MIPS_32:
|
|
*p = s + *p;
|
|
break;
|
|
|
|
case R_MIPS_26:
|
|
{
|
|
Elf_Addr a = *p & 0x03ffffff;
|
|
Elf_Addr val = ((a << 2) | ((Elf_Addr)p & 0xf0000000)) + s;
|
|
val = (val >> 2) & 0x03ffffff;
|
|
*p &= 0xfc000000;
|
|
*p |= val;
|
|
}
|
|
break;
|
|
|
|
case R_MIPS_HI16:
|
|
if (data->pos >= MIPS_HI16_COUNT)
|
|
{
|
|
return -EINVAL;
|
|
}
|
|
|
|
data->ahi = *p;
|
|
data->hi[data->pos].ahi = *p;
|
|
data->hi[data->pos].p = p;
|
|
|
|
data->pos++;
|
|
|
|
break;
|
|
|
|
case R_MIPS_LO16:
|
|
{
|
|
int i;
|
|
int16_t a = *p;
|
|
Elf_Addr ahl = (data->ahi << 16) + a;
|
|
Elf32_Addr iword = *p & 0xffff0000;
|
|
iword |= (uint16_t)(ahl + s);
|
|
*p = iword;
|
|
|
|
for (i = 0; i < data->pos; i++)
|
|
{
|
|
ahl = (data->hi[i].ahi << 16) + a;
|
|
|
|
iword = *(data->hi[i].p) & 0xffff0000;
|
|
iword |= ((ahl + s) - (int16_t)(ahl + s)) >> 16;
|
|
*(data->hi[i].p) = iword;
|
|
}
|
|
|
|
data->pos = 0;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
berr("ERROR: Unsupported relocation: %" PRIu32 "\n",
|
|
ELF_R_TYPE(rel->r_info));
|
|
return -EINVAL;
|
|
}
|
|
|
|
return OK;
|
|
}
|
|
|
|
int up_relocateadd(const Elf32_Rela *rela, const Elf32_Sym *sym,
|
|
uintptr_t addr, void *arch_data)
|
|
{
|
|
berr("Not implemented\n");
|
|
PANIC();
|
|
return -ENOSYS;
|
|
}
|
|
|