Java 2 Ada

GCC 6.1 Ada Compiler From Scratch

By stephane.carrez

GCC 6.1 release has been announced recently by Jakub Jelinek and it is now time to build a new Ada compiler with it. The process to do that is not complex but contains a few pitfalls. We will do the following tasks:

  1. The binutils build and installation,
  2. The gcc build and installation,
  3. Setting up a default configuration for gprbuild,
  4. The XML/Ada build and installation,
  5. The gprbuild build and installation.

Pre-requisites

First, prepare three distinct directories for the sources, the build materials and the installation. Make sure you have more than 1.5G for the source directory, reserve 7.0G for the build directory and arround 1.5G for the installation directory.

To simplify the commands, define the following shell variables:

BUILD_DIR=<Path of build directory>
INSTALL_DIR=<Path of installation directory>
SRC_DIR=<Path of directory containing the extracted sources>

Also, check that:

  • You have a GNAT Ada compiler installed (at least a 4.9 I guess).
  • You have the gprbuild tool installed and configured for the Ada compiler.
  • You have libmpfr-dev, libgmp3-dev and libgmp-dev installed (otherwise this is far more complex).
  • You have some time and can wait for gcc's compilation (it took more than 2h for me).

Create the directories:

mkdir -p $BUILD_DIR
mkdir -p $INSTALL_DIR/bin
mkdir -p $SRC_DIR

And setup your PATH so that you will use the new binutils and gcc commands while building everything:

export PATH=$INSTALL_DIR/bin:/usr/bin:/bin

Binutils

Download binutils 2.26 and extract the tar.bz2 in the source directory $SRC_DIR.

cd $SRC_DIR
tar xf binutils-2.26.tar.bz2

Never build the binutils within their sources, you must use the $BUILD_DIR for that. Define the installation prefix and configure the binutils as this:

mkdir $BUILD_DIR/binutils
cd $BUILD_DIR/binutils
$SRC_DIR/binutils-2.26/configure --prefix=$INSTALL_DIR

And proceed with the build in the same directory:

make

Compilation is now complete you can install the package:

make install

Gcc

Download gcc 6.1.0 and extract the tar.bz2 in the source directory $SRC_DIR.

cd $SRC_DIR
tar xf gcc-6.1.0.tar.bz2

Again, don't build gcc within its sources and use the $BUILD_DIR directory. At this stage, it is important that your PATH environment variable uses the $INSTALL_DIR/bin first to make sure you will use the new installed binutils tools. You may add the --disable-bootstrap to speed up the build process.

mkdir $BUILD_DIR/gcc
cd $BUILD_DIR/gcc
$SRC_DIR/gcc-6.1.0/configure --prefix=$INSTALL_DIR --enable-languages=c,c++,ada

And proceed with the build in the same directory (go to the restaurant or drink a couple of beers while it builds):

make

Compilation is now complete you can install the package:

make install

The Ada compiler installation does not install two symbolic links which are required during the link phase of Ada libraries and programs. You must create them manually after the install step:

ln -s libgnarl-6.so $INSTALL_DIR/lib/gcc/x86_64-pc-linux-gnu/6.1.0/adalib/libgnarl-6.1.so
ln -s libgnat-6.so $INSTALL_DIR/lib/gcc/x86_64-pc-linux-gnu/6.1.0/adalib/libgnat-6.1.so

Setup the default.cgpr file

The gnatmake command has been deprecated and it is now using gprbuild internally. This means we need a version of gprbuild that uses the new compiler. One way to achieve that is by setting up a gprbuild configuration file:

cd $BUILD_DIR
gprconfig

Select the Ada and C compiler and then edit the default.cgpr file that was generated to change the Toolchain_Version, Runtime_Library_Dir, Runtime_Source_Dir, Driver to indicate the new gcc 6.1 installation paths (replace <INSTALL_DIR> with your installation directory):

configuration project Default is
   ...
   for Toolchain_Version     ("Ada") use "GNAT 6.1";
   for Runtime_Library_Dir   ("Ada") use "<INSTALL_DIR>/lib/gcc/x86_64-pc-linux-gnu/6.1.0//adalib/";
   for Runtime_Source_Dir    ("Ada") use "<INSTALL_DIR>/lib/gcc/x86_64-pc-linux-gnu/6.1.0//adainclude/";
   package Compiler is
      for Driver ("C") use "<INSTALL_DIR>/bin/gcc";
      for Driver ("Ada") use "<INSTALL_DIR>/bin/gcc";
      ...
   end Compiler;
   ...
end Default;

This is the tricky part because if you missed it you may end up using the old Ada compiler. Make sure the Runtime_Library_Dir and Runtime_Source_Dir are correct otherwise you'll have problems during builds. As far as I'm concerned, the gcc target triplet was also changed from x86_64-linux-gnu to x86_64-pc-linux-gnu. Hopefully, once we have built a new gprbuild everything will be easier. The next step is to build XML/Ada which is used by gprbuild.

XML/Ada

Download and extract the XML/Ada sources. Using the git repository works pretty well:

cd $BUILD_DIR
git clone https://github.com/AdaCore/xmlada.git xmlada

This time we must build within the sources. Before running the configure script, the default.cgpr file is installed so that the new Ada compiler is used:

cp $BUILD_DIR/default.cgpr $BUILD_DIR/xmlada/
cd $BUILD_DIR/xmlada
./configure --prefix=$INSTALL_DIR

And proceed with the build in the same directory:

make static shared

Compilation is now complete you can install the package:

make install-static install-relocatable

gprbuild

Get the gprbuild sources from the git repository:

cd $BUILD_DIR
git clone https://github.com/AdaCore/gprbuild.git gprbuild

Copy the default.cgpr file to the gprbuild source tree and run the configure script:

cp $BUILD_DIR/default.cgpr $BUILD_DIR/gprbuild/
cd $BUILD_DIR/gprbuild
./configure --prefix=$INSTALL_DIR

Setup the ADA_PROJECT_PATH environment variable to use the XML/Ada library that was just compiled. If you miss this step, you'll get a file dom.ali is incorrectly formatted error during the bind process.

export ADA_PROJECT_PATH=$INSTALL_DIR/lib/gnat

And proceed with the build in the same directory:

make

Compilation is now complete you can install the package:

make install

Using the compiler

Now you can remove the build directory to make some space. You'll not need the default.cgpr file anymore nor define the ADA_PROJECT_PATH environment variable (except for other needs). To use the new Ada compiler you only need to setup your PATH:

export PATH=$INSTALL_DIR/bin:/usr/bin:/bin

You're now ready to play and use the GCC 6.1 Ada Compiler.

To add a comment, you must be connected. Login to add a comment

Ada BFD 1.1.0 is available

By stephane.carrez

Ada BFD is an Ada binding for the GNU Binutils BFD library. It allows to read binary ELF, COFF files by using the GNU BFD and allows your program to read ELF sections, get access to the symbol table and use the disassembler.

I've added the support to the GNU demangler so that it is now possible to demangle symbols. You can demangle C++, Java and Ada symbols. To use the demangler you need a BFD file which is a limited type.

with Bfd.Files;
with Bfd.Symbols;
  ...
  File : Bfd.Files.File_Type;

The BFD file is opened as follows:

  Bfd.Files.Open (File, Path, "");

Then, you may convert any symbol name using the Demangle function:

  Name : String := Bfd.Symbols.Demangle (File, "bfd__symbols__get_name",
                                         Constants.DMGL_GNAT);

Sources are now moved to GitHub: https://github.com/stcarrez/ada-bfd

You can download the release at: http://download.vacs.fr/ada-bfd/ada-bfd-1.1.0.tar.gz

To add a comment, you must be connected. Login to add a comment

Ada BFD 1.0.1 is available

By stephane.carrez

Ada BFD is an Ada binding for the GNU Binutils BFD library.

It allows to read binary ELF, COFF files by using the GNU BFD and allows your program to read ELF sections, get access to the symbol table and use the disassembler.

The new version fixes build and compilation issues with recent releases of GNU Binutils and it also provides support to build Debian packages.

http://download.vacs.fr/ada-bfd/ada-bfd-1.0.1.tar.gz

To add a comment, you must be connected. Login to add a comment

Ada BFD 1.0 is available

By stephane.carrez

Ada BFD is an Ada binding for the GNU Binutils BFD library.

It allows to read binary ELF, COFF files by using the GNU BFD. The Ada BFD library allows to:

      list and scan the ELF sections of an executable or object file,
    
        get the content of the ELF sections,
      
          get access to the symbol table,
        
            use the BFD disassembler 
          

          Version 1.0 of this Ada binding library is now available on Ada BFD. This new release bring the following changes:

          • Fixed installation of library
          • Added examples for BfdAda
          • Add support to use the disassembler
          To add a comment, you must be connected. Login to add a comment

          Reading a program symbol table with Ada BFD

          By stephane.carrez

          The GNU Binutils provides support for reading and writing program files in various formats such as ELF, COFF. This support is known as the BFD, the Binary File Descriptor library (or the Big F*cking Deal). This article illustrates how an Ada application can use the BFD library to have access to a program symbol table.

          Declarations

          The Ada BFD library provides a set of Ada bindings that give access to the BFD library. A binary file such as an object file, an executable or an archive is represented by the Bfd.Files.File_Type limited type. The symbol table is represented by the Bfd.Symbols.Symbol_Table limited type. These two types hold internal data used and managed by the BFD library.

          with Bfd.Files;
          with Bfd.Sections;
          with Bfd.Symbols;
          ...
            File    : Bfd.Files.File_Type;
            Symbols : Bfd.Symbols.Symbol_Table;
          

          Opening the BFD file

          The Open procedure must be called to read the object or executable file whose path is given as argument. The File_Type parameter will be initialized to get access to the binary file information. The Check_Format function must then be called to let the BFD library gather the file format information and verify that it is an object file or an executable.

          Bfd.Files.Open (File, Path, "");
          if Bfd.Files.Check_Format (File, Bfd.Files.OBJECT) then
              ...
          end if;
          

          Loading the symbol table

          The symbol table is loaded by using the Read_Symbols procedure.

             Bfd.Symbols.Read_Symbols (File, Symbols);
          

          The resources used by the symbol table will be freed when the symbol table instance is finalized.

          Looking for a symbol

          Once the symbol table is loaded, we can use the Get_Symbol function to find a symbol knowing its name. If the symbol is not found, a Null_Symbol is returned.

          Sym  : Bfd.Symbols.Symbol := Bfd.Symbols.Get_Symbol (Symbols, "_main");
          ...
          if Sym /= Bfd.Symbols.Null_Symbol then
             --  Symbol found
          end if;
          

          Each symbol has the following set of information:

          • A name (it may not be unique),
          • A set of flags that describe the symbol (global, local, weak, constructor, TLS, ...),
          • A symbol value,
          • A section to which the symbol belongs.
          Sec   : constant Bfd.Sections.Section := Bfd.Symbols.Get_Section (Sym);
          Flags : constant Bfd.Symbol_Flags     := Bfd.Symbols.Get_Flags (Sym);
          Value : constant Bfd.Symbol_Value    := Bfd.Symbols.Get_Value (Sym);
          

          Before interpreting and using the symbol value returned by Get_Value, you must look at the section to check for an undefined symbol. Indeed, undefined symbols being not yet resolved by the linker they have no value and no section. You can check that by using the Is_Undefined_Section function:

          if Bfd.Sections.Is_Undefined_Section (Sec) then
             Ada.Text_IO.Put_Line ("undefined symbol");
          end if;
          

          When the symbol is defined, you must look at the flags and also the section information to know more about it.

          if (Flags and Bfd.Symbols.BSF_GLOBAL) /= 0 then
            Ada.Text_IO.Put_Line ("global symbol in section "
                         & Bfd.Sections.Get_Name (Sec)
                         & " := " & Bfd.Symbol_Value'Image (Value));
          
          elsif (Flags and Bfd.Symbols.BSF_LOCAL) /= 0 then
            Ada.Text_IO.Put_Line ("local symbol in section "
                         & Bfd.Sections.Get_Name (Sec)
                         & " := " & Bfd.Symbol_Value'Image (Value));
          
          else
            Ada.Text_IO.Put_Line ("other symbol in section "
                                               & Bfd.Sections.Get_Name (Sec)
                                               & " := " & Bfd.Symbol_Value'Image (Value));
          end if;
          

          Conclusion and references

          Reading an executable symbol table has been made fairly simple with the use of the Ada BFD library. Furthermore, the library allows to scan the sections, read their content and even use the BFD disassembler.

          symbol.adb

          BFD Documentation

          To add a comment, you must be connected. Login to add a comment
          • Page 1