nuttx/libs/libc/elf/elf_depend.c
chao an 52482219c8 libc/elf: rename modlib to libelf
Renaming "modlib" to "libelf" is more in line with the implementation content,
which makes it easier for individual developers to understand the capabilities of this module.

CONFIG_LIBC_MODLIB -> CONFIG_LIBC_ELF

Signed-off-by: chao an <anchao.archer@bytedance.com>
2025-04-11 09:43:22 +08:00

184 lines
5.6 KiB
C

/****************************************************************************
* libs/libc/elf/elf_depend.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 <stdlib.h>
#include <assert.h>
#include <errno.h>
#include <debug.h>
#include <nuttx/lib/elf.h>
#if CONFIG_LIBC_ELF_MAXDEPEND > 0
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: libelf_depend
*
* Description:
* Set up module dependencies between the exporter and the importer of a
* symbol. The happens when the module is installed via insmod and a
* symbol is imported from another module.
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
* Assumptions:
* Caller holds the registry lock.
*
****************************************************************************/
int libelf_depend(FAR struct module_s *importer,
FAR struct module_s *exporter)
{
int freendx = -1;
int i;
DEBUGASSERT(importer != NULL && exporter != NULL);
/* First checker if the exported is already in our list if dependencies.
* This would happen if we are importing multiple symbols from the same
* exporting module. In that case, the module would already be in the
* list of dependencies.
*
* The list dependency list is a a dumb, upacked array of pointers. This
* should not be too inefficient if the number of CONFIG_LIBC_ELF_MAXDEPEND
* is small. Otherwise, a more dynamic data structure would be in order.
*/
for (i = 0; i < CONFIG_LIBC_ELF_MAXDEPEND; i++)
{
FAR const struct module_s *modp;
/* Check if this dependency slot is available. */
modp = importer->dependencies[i];
if (modp == NULL)
{
/* Remember this slot for use the module is NOT already in the
* list of dependencies.
*/
freendx = i;
}
else if (modp == exporter)
{
/* Yes, we are already importing symbols from this module. Nothing
* more needs to be done.
*/
return OK;
}
}
/* If we get here, then (1) this is a new exporting module that does not
* already appear in the list of dependencies, and (2) freendx is the
* index to the last free slot in the dependency list. If freendx is
* negative, then the dependency list is full.
*/
if (freendx >= 0)
{
/* Increment the count of dependencies on the exporter module */
DEBUGASSERT(exporter->dependents < UINT8_MAX);
if (exporter->dependents >= UINT8_MAX)
{
return -ENOSPC;
}
exporter->dependents++;
/* And remember the exporter so that we can decrement the count of
* dependents if the importer is removed.
*/
DEBUGASSERT(importer->dependencies[freendx] == NULL);
importer->dependencies[freendx] = exporter;
return OK;
}
/* If we get there then the list of dependencies is full. */
DEBUGPANIC();
return -ENFILE;
}
/****************************************************************************
* Name: libelf_undepend
*
* Description:
* Tear down module dependencies between the exporters and the importer of
* symbols. This happens when the module is removed via rmmod (and on
* error handling cases in insmod).
*
* Returned Value:
* 0 (OK) is returned on success and a negated errno is returned on
* failure.
*
* Assumptions:
* Caller holds the registry lock.
*
****************************************************************************/
int libelf_undepend(FAR struct module_s *importer)
{
FAR struct module_s *exporter;
int i;
DEBUGASSERT(importer != NULL && importer->dependents == 0);
/* Decrement the dependency count on each of exporters of symbols used by
* this importer module. This is an upacked array of pointers. This
* should not be too inefficient if the number of CONFIG_LIBC_ELF_MAXDEPEND
* is small. Otherwise, a more dynamic data structure would be in order.
*/
for (i = 0; i < CONFIG_LIBC_ELF_MAXDEPEND; i++)
{
exporter = importer->dependencies[i];
if (exporter != NULL)
{
DEBUGASSERT(exporter->dependents > 0);
if (exporter->dependents > 0)
{
exporter->dependents--;
}
importer->dependencies[i] = NULL;
}
}
return OK;
}
#endif