Development Guidelines

Available APIs

Table 1 Functions

Category

API

Description

Dynamic loading

LOS_DynlinkInit

Initializes the dynamic linker linked list and mutex.

LOS_SoLoad

Loads the shared library in a specified path.

LOS_FindSym

Searches for the specified symbol based on the shared library handle.

LOS_SoUnload

Unloads the shared library handle.

How to Develop

  1. Use the arm-none-eabi-gcc cross compiler to compile the shared library and build a FAT or LittleFS image, and burn the image to the flash memory.
  2. In the target_config.h file, set LOSCFG_DYNLINK to 1 to enable the dynamic loading module.
  3. Call LOS_SoLoad to load the shared library in the specified path.
  4. Call LOS_FindSym to search for the specified symbol and obtain the symbol address.
  5. Call LOS_SoUnload to unload the handle of the specified shared library.

NOTE:

  1. For details about the compilation options required for compiling the shared library using the cross compiler, see the ELF specifications.
  2. Before creating a file system image, you need to adapt the FAT or LittleFS to the specific board.
  3. The shared library does not depend on the libc library in the compiler and does not support C++.
  4. The shared library depends only on the APIs provided by the kernel and cannot depend on other shared libraries.

Development Example

The following uses the Arm Cortex-M4 board as an example.

  1. Sample Code and Compilation of the Shared Library

    The sample code is used to test the calling of global symbols and calling of the kernel APIs malloc, free, and memset.

    #include <stdlib.h>
    #include <string.h>
    
    int g_param = 10;
    
    int callee(int a, int b)
    {
        char *addr = malloc(g_param);
        if (addr == NULL) {
            return 0;
        }
    
        memset(addr, '1', g_param);
    
        free(addr);
        return a + b + g_param;
    }
    
    int caller(int a, int b)
    {
        return callee(a, b);
    }
    
    $ arm-none-eabi-gcc -fPIC -shared -mcpu=cortex-m4 -nostdlib -nostartfiles -z max-page-size=4 -o test.so test.c
    
  2. Export the malloc, free, and memset symbols used in the shared library. Compile the following code into a .c file and use it for OS compilation.

    #include "stdlib.h"
    #include "string.h"
    
    SYM_EXPORT(malloc);
    SYM_EXPORT(free);
    SYM_EXPORT(memset);
    
  3. Determine the kernel compilation environment and add the following statement to the linking script of the compiler to ensure that the symbol table information is output to the specified section during compilation and linking.

    Add the following statement to the .icf linking script of the IAR compiler:

    keep {section .TABLE.START};
    keep {section .sym.*};
    keep {section .table.end};
    define block SYMBOL_TABLE with fixed order
    {
        section .TABLE.START,
        section .sym.*,
        section .table.end
    };
    place in ROM_region {readonly, block SYMBOL_TABLE};
    

    Add the following statement to the .ld linking script of the GCC compiler:

    __sym_table_start = .;
    KEEP(*( SORT (.sym.*)));
    __sym_table_end = .;
    
  4. Load, link, execute, and unload the shared library.

    The sample code is used to test whether the functions of the LOS_SoLoad, LOS_FindSym, and LOS_SoUnload can be implemented normally and whether the symbols located by using LOS_FindSym can be properly called.

    #include "los_dynlink.h"
    
    VOID DynlinkTest(VOID)
    {
        VOID *handle = NULL;
        INT32 (*func)(INT32, INT32) = NULL;
        CHAR *symbolName = "caller";
        CHAR *dsoName = "/lib/test.so";
        INT32 ret;
    
        handle = (VOID *)LOS_SoLoad(dsoName, NULL);
        if (handle == NULL) {
            printf("Failed to load so\n");
            return;
        }
    
        func = (INT32 (*)(INT32, INT32))LOS_FindSym(handle, symbolName);
        if (func == NULL) {
            printf("Failed to find symbol\n");
            LOS_SoUnload(handle);
            return;
        }
    
        ret = func(1, 1);
        if (ret != 12) {
            printf("Failed to execute function\n");
            LOS_SoUnload(handle);
            return;
        }
    
        ret = LOS_SoUnload(handle);
        if (ret != 0) {
            printf("Failed to unload so\n");
        }
    	
    	
        printf("Success!\n");
    }
    
  5. Verification

    Success!
    

NOTE: In this example, the file system path is /lib/test.so. You can create a task and call DynlinkTest in the task to perform the test.