We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 19
LEC 03 Md Samin Rahman
BUILD TARGET IMAGES (OS)
In this section, we will look at the
toolchain for building target images, and introduce a standard object file format— ELF. As a case study, we will also examine the image building process for embedded systems that rely on the QNX operating system. Cross-Development Toolchain: Figure 2.2 shows the code transformation process involving a chain of cross- development tools: cross compiler/assembler, linker, and dynamic linker Cross Compiler/Assembler Compilers and assemblers are essential tools in software development, especially when dealing with different hardware and software environments. Here’s a breakdown of what a cross compiler and a cross assembler are, how they work, and their applications: Native Compiler vs. Cross Compiler: Native Compiler: A native compiler generates executable code for the same platform on which it runs. For example, if you’re compiling code on a Windows machine and the output is intended to run on that same Windows machine, you’re using a native compiler. Cross Compiler: A cross compiler generates executable code for a different platform from the one it is running on. This means you can compile code on one system (the host) to run on another system (the target), which might have different hardware or operating system specifications. Cross Assembler: A cross assembler is similar to a cross compiler but works with assembly language source files. It assembles code for a target platform different from the one on which the assembler runs. Why Use a Cross Compiler/Assembler? Limited Resources on Target Platforms: Target platforms, such as embedded systems, often have limited resources and might not be powerful enough to run a native compiler. In these cases, a cross compiler can be used on a more powerful host machine to generate executable code for the resource- constrained target system. Multiple Target Platforms: When a project needs to run on various target platforms— such as different processor types, operating system versions, or even different operating systems—a cross compiler allows you to set up a single development environment on the host machine that can compile code for all these different targets. Object Files and Symbol Tables Object Files: During compilation, the cross compiler/assembler generates object files. Each object file contains compiled code and data, which is a part of the final executable. For instance, if you compile two source files, you will get two object files, such as one.o and two.o. Symbol Tables: Each object file includes a symbol table, which is a data structure that holds information about symbols in the code. These symbols include: Global Symbols: Names of global variables and non-static functions defined in the compilation unit. External Symbols: Symbols with external linkage that are referenced but defined elsewhere. The symbol table helps the compiler and linker locate and manage symbolic definitions and references. It includes: Global Symbol Definitions: For example, in one source file (one.c), global symbols might include variables and functions like c, sa, sb, and main(). External Symbol References: For symbols defined in other files, such as a and b() referenced in one.c but defined elsewhere. Local Symbols: Local variables with static storage duration, like temp, are also included in the symbol table but are only visible within their respective compilation units. Linker: A linker is a crucial component in the software development process, responsible for combining multiple object files into a single executable or shared object file. This process ensures that the various pieces of code and data defined across different files work together seamlessly. Symbol Resolution is the first major task performed by the linker. When a linker processes an application, it needs to resolve symbols with external linkage, which means identifying where each symbol is defined and ensuring that all references to these symbols are correctly matched. Symbols can be variables or functions defined across different object files. The linker must also consider symbols from application-independent libraries, such as standard functions (e.g., printf) that are used in many programs. If two variables have the same name but are defined in different files, the linker differentiates them using their file context. For instance, if a variable named sb is declared in both one.c and two.c, the linker treats these as separate symbols due to their distinct origins. Symbol Relocation is the second major task of the linker. Once the linker has resolved all symbols and their locations, it adjusts the addresses of these symbols in the final object file. During the linking process, the addresses of symbols may need to be updated to reflect their actual locations in memory. This adjustment is managed through a relocation table, which keeps track of where symbols are placed and helps the linker modify the binary code accordingly. Essentially, relocation ensures that the code and data from different object files are correctly positioned and referenced in the final executable. The linker can produce three different types of object files: Relocatable File: Definition: A relocatable file is an intermediate object file generated by a compiler. It contains machine code but is not yet linked to other object files or libraries. Purpose: This file contains code and data that can be relocated to different addresses in memory. It is designed to be linked with other relocatable files to produce an executable or a shared object file. File Extensions: Common extensions include .o (object file) or .obj. Shared Object File: Definition: A shared object file is a dynamically linked library that can be shared among multiple programs. It contains code and data that can be loaded into memory and used by applications at runtime. Purpose: These files allow code to be reused across different programs, which can reduce memory usage and disk space. They also support dynamic linking, where the linking is done at runtime rather than compile time. File Extensions: Common extensions include .so (on Linux) and .dll (on Windows). The linker can produce three different types of object files: Executable File: Definition: An executable file is a binary file that is ready to be run by the operating system. It is the final product after linking all object files and libraries together. Purpose: This file contains the complete machine code necessary to execute a program. It can be directly executed by the operating system to run the program. File Extensions: Common extensions include .exe (on Windows) and no extension or .out (on Linux). Dynamic Linker: When an object file needs to be executed, it must be loaded into the computer's RAM. This task is handled by a special program called a program interpreter. The program interpreter is essentially an executable or shared object file that is capable of running other programs. It provides the necessary environment for the object file to execute by managing its loading and execution process. Program Loader: is a basic type of program interpreter. Its primary job is to load an executable file into memory and then transfer control to that file so it can start running. This approach works well for stand-alone executable files, which include all the necessary library routines embedded within them. While this makes the executable file easier to distribute—since it does not depend on external libraries—it also results in larger file sizes and greater memory usage, as each copy of the executable contains its own libraries. In contrast, some programs do not contain all the library routines directly within the executable file. Instead, they include only references to shared library routines. This means that the actual library files need to be present on the target system for the program to run. To handle this, a more sophisticated type of program interpreter called a dynamic linker is used. The dynamic linker performs several tasks: Initial Loading: It first loads the entire program into memory, creating an initial process image. This process includes setting up the memory space where the program will run. Dynamic Linking: Next, it resolves any symbolic references in the program by dynamically loading and binding the required external shared libraries. This step effectively completes the process image by linking the necessary libraries at runtime. Control Transfer: Finally, the dynamic linker transfers control to the process, allowing the program to start execution. Dynamic linking has significant advantages. One major benefit is that multiple applications can share a single copy of a library, which reduces memory usage and storage requirements. Additionally, if a shared library is updated with bug fixes or improvements, all programs using that library can automatically benefit from these changes without needing to be recompiled or redistributed. This makes dynamic linking a powerful tool for managing software dependencies and keeping systems up-to-date. BUILD TARGET IMAGES
Case Study: Building a QNX Image
A QNX image is a holistic executable file containing both the QNX operating system and user applications, designed to run on a specific target board. This process involves creating a single integrated image that can be loaded and executed on the target hardware. A QNX image refers to the file or binary that contains a complete QNX operating system environment, which is used for embedded systems. QNX is a real-time operating system known for its reliability and efficiency in handling time-critical tasks. The image is typically written to a storage medium such as flash memory, a hard drive, or other types of persistent storage within the embedded device. Once deployed, it allows the device to boot up and run the QNX operating system. A "QNX image" is essentially a single, comprehensive executable file that combines both user applications and the QNX operating system. Building a QNX image for a specific target board involves several steps to ensure that the software is compatible with the hardware it will run on. The process typically begins with obtaining a board support package (BSP), which is a crucial software component designed to support the specific hardware design of the target board. Most commercial evaluation boards come with a sample BSP, which is highly beneficial as it saves developers a significant amount of time and effort that would otherwise be spent writing low-level software from scratch. A QNX BSP typically includes an initial program loader, which is necessary for loading the QNX operating system onto the board, and a startup module that contains all the device drivers required for the hardware. This startup module is essential because it provides the necessary instructions for the operating system to communicate effectively with the various hardware components of the board, such as the CPU, memory, and input/output devices. To bring all these components together, a system builder project is needed. This project serves as a framework for integrating the different parts of the software and hardware support. The system builder project is processed by a utility called "mkifs" (make image filesystem). The mkifs utility creates a bootable QNX image from the components specified in a build-script file (often with a ".bld" extension). This script file can be customized to ensure that the final QNX image contains all the necessary elements. For example, it includes the startup binary from the BSP, the QNX kernel, and relevant shared library objects that are essential for the operating system's core functions. Additionally, it incorporates application-specific binaries, which are generated from user projects, and other relevant libraries and utilities required for the software to function correctly. The startup binary is an executable file that is loaded first when an embedded system powers up. It initializes the hardware and sets up the system environment. The BSP is a collection of software and configuration files that support the specific hardware of an embedded system. It includes drivers, initialization code, and other hardware-specific components. The QNX kernel is the core part of the QNX operating system that manages system resources and hardware interactions. It handles process management, memory management, and hardware communication. The final QNX image for an embedded system consists of two main parts: the initial program loader (provided by the BSP) and the bootable QNX image created by mkifs. The initial program loader is responsible for loading the QNX operating system and user applications into memory when the embedded system starts up. Meanwhile, the bootable QNX image contains all the necessary software components for the system to operate, including the operating system kernel, device drivers, user applications, and various utilities. This comprehensive image ensures that the embedded system is fully functional and capable of running the desired software in a stable and efficient manner. Transferring an executable file object to the target system typically involves using a utility known as a "programmer." This utility is responsible for writing the executable file to the non-volatile memory (NVM), such as ROM or flash memory, on the target system. The process is sometimes referred to as "high-voltage programming," which ensures that the data is correctly written to the memory, even if the memory type requires higher voltage levels to accept new data. For example, in the process of building a QNX image for a specific target board, a programmer called SAM- BA (Software Atmel Microcontroller Boot Assistant) is used to transfer the final QNX image to the target board. SAM-BA is a commonly used tool that facilitates the communication between a development system and a target board, allowing the transfer of executable files over various interfaces, such as USB or serial ports. Once the executable file object is successfully transferred and stored in the NVM on the target board, it becomes accessible to the processor. At this point, the processor can execute the file, which means the target platform is ready to run the embedded system application or operating system contained within the transferred executable. This process is crucial for deploying software to embedded systems, ensuring that the final executable is properly loaded and ready for operation in the target environment.
Introduction to various system programs such as Assembler, Macro processor, Loader, Linker, Compiler, Interpreter, Device Drivers, Operating system, Editors, Debuggers._9049ce67290423e469cbf393c1bded2e