Task 726: .TGT File Format

Task 726: .TGT File Format

File Format Specifications for .TGT

The .TGT file format is used in the GNU Binutils linker (ld) as a configuration script for target-specific settings. It is a plain text shell script that defines how the linker is configured for different architectures and operating systems. The file is not a binary format but a executable shell script that sets variables based on the target triple.

1. List of All Properties of This File Format Intrinsic to Its File System

The properties are the variables set within the file, which define the configuration for each target pattern. These are intrinsic to the format as they are the core data the script provides:

  • targ_emul: The primary linker emulation name for the target.
  • targ_extra_emuls: A list of additional linker emulations available for the target.
  • targ_extra_libpath: Additional library search paths for the emulations.
  • targ_extra_ofiles: Additional object files required by the emulation.
  • targ64_extra_emuls: Additional emulations for 64-bit configurations (when applicable).
  • targ64_extra_libpath: Additional library paths for 64-bit configurations (when applicable).
  • NATIVE_LIB_DIRS: Directory paths for native libraries on the host system.

These properties are assigned per target pattern (e.g., "aarch64--linux") via a case statement in the script. The file system properties (e.g., file size, creation date, permissions) are standard for any text file and not specific to the format.

3. Ghost Blog Embedded HTML JavaScript for Drag and Drop .TGT File Dump

The following is a complete HTML page with embedded JavaScript that allows a user to drag and drop a .TGT file. It parses the file to extract the properties for each target pattern and displays them on the screen.

.TGT File Property Dumper

Drag and Drop .TGT File

Drop .TGT file here

4. Python Class for .TGT File Handling

The following Python class can open, decode (parse), read (extract properties), write (generate file from properties), and print the properties to console.

import re

class TGTFile:
    def __init__(self, filename=None):
        self.properties = {}
        if filename:
            self.read(filename)

    def read(self, filename):
        with open(filename, 'r') as f:
            content = f.read()
        self.properties = self.parse(content)

    def parse(self, content):
        properties = {}
        current_target = None
        for line in content.splitlines():
            line = line.strip()
            if line.endswith(')'):
                current_target = line[:-1].strip()
                properties[current_target] = {}
            elif '=' in line and current_target:
                key, value = line.split('=', 1)
                key = key.strip()
                value = value.strip().replace(';;', '')
                if key in ['targ_emul', 'targ_extra_emuls', 'targ_extra_libpath', 'targ_extra_ofiles', 'targ64_extra_emuls', 'targ64_extra_libpath', 'NATIVE_LIB_DIRS']:
                    properties[current_target][key] = value
        return properties

    def print_properties(self):
        for target, props in self.properties.items():
            print(f"Target: {target}")
            for key, value in props.items():
                print(f"  {key}: {value}")
            print()

    def write(self, filename):
        with open(filename, 'w') as f:
            f.write('# Sample .TGT configuration script\n')
            f.write('targ_emul=\n')
            f.write('targ_extra_emuls=\n')
            f.write('targ_extra_libpath=\n')
            f.write('targ_extra_ofiles=\n')
            f.write('targ64_extra_emuls=\n')
            f.write('targ64_extra_libpath=\n')
            f.write('case "${targ}" in\n')
            for target, props in self.properties.items():
                f.write(f'  {target})\n')
                for key, value in props.items():
                    f.write(f'    {key}={value} ;;\n')
            f.write('  *) echo "${targ} emulation unknown." ;;\n')
            f.write('esac\n')
            f.write('case "${targ_obj}" in\n')
            f.write('  # NATIVE_LIB_DIRS setting\n')
            f.write('esac\n')

# Example usage
if __name__ == "__main__":
    tgt = TGTFile('example.tgt')
    tgt.print_properties()
    tgt.write('output.tgt')

5. Java Class for .TGT File Handling

The following Java class can open, decode (parse), read (extract properties), write (generate file from properties), and print the properties to console.

import java.io.*;
import java.util.*;

public class TGTFile {
    private Map<String, Map<String, String>> properties = new HashMap<>();

    public TGTFile(String filename) throws IOException {
        read(filename);
    }

    public TGTFile() {}

    public void read(String filename) throws IOException {
        StringBuilder content = new StringBuilder();
        try (BufferedReader br = new BufferedReader(new FileReader(filename))) {
            String line;
            while (line = br.readLine() != null) {
                content.append(line).append("\n");
            }
        }
        parse(content.toString());
    }

    private void parse(String content) {
        properties.clear();
        String[] lines = content.split("\n");
        String currentTarget = null;
        for (String line : lines) {
            line = line.trim();
            if (line.endsWith(")")) {
                currentTarget = line.substring(0, line.length() - 1).trim();
                properties.put(currentTarget, new HashMap<>());
            } else if (line.contains("=") && currentTarget != null) {
                String[] parts = line.split("=", 2);
                String key = parts[0].trim();
                String value = parts[1].trim().replace(";;", "");
                if (key.matches("targ_.*|NATIVE_LIB_DIRS")) {
                    properties.get(currentTarget).put(key, value);
                }
            }
        }
    }

    public void printProperties() {
        for (Map.Entry<String, Map<String, String>> entry : properties.entrySet()) {
            System.out.println("Target: " + entry.getKey());
            for (Map.Entry<String, String> prop : entry.getValue().entrySet()) {
                System.out.println("  " + prop.getKey() + ": " + prop.getValue());
            }
            System.out.println();
        }
    }

    public void write(String filename) throws IOException {
        try (BufferedWriter bw = new BufferedWriter(new FileWriter(filename))) {
            bw.write("# Sample .TGT configuration script\n");
            bw.write("targ_emul=\n");
            bw.write("targ_extra_emuls=\n");
            bw.write("targ_extra_libpath=\n");
            bw.write("targ_extra_ofiles=\n");
            bw.write("targ64_extra_emuls=\n");
            bw.write("targ64_extra_libpath=\n");
            bw.write("case \"${targ}\" in\n");
            for (Map.Entry<String, Map<String, String>> entry : properties.entrySet()) {
                bw.write("  " + entry.getKey() + ")\n");
                for (Map.Entry<String, String> prop : entry.getValue().entrySet()) {
                    bw.write("    " + prop.getKey() + "=" + prop.getValue() + " ;;\n");
                }
            }
            bw.write("  *) echo \"${targ} emulation unknown.\" ;;\n");
            bw.write("esac\n");
            bw.write("case \"${targ_obj}\" in\n");
            bw.write("# NATIVE_LIB_DIRS setting\n");
            bw.write("esac\n");
        }
    }

    // Example usage
    public static void main(String[] args) throws IOException {
        TGTFile tgt = new TGTFile("example.tgt");
        tgt.printProperties();
        tgt.write("output.tgt");
    }
}

6. JavaScript Class for .TGT File Handling

The following JavaScript class can open (using FileReader), decode (parse), read (extract properties), write (generate blob for download), and print the properties to console.

class TGTFile {
    constructor() {
        this.properties = {};
    }

    read(file) {
        return new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.onload = (event) => {
                this.parse(event.target.result);
                resolve();
            };
            reader.onerror = reject;
            reader.readAsText(file);
        });
    }

    parse(content) {
        this.properties = {};
        const lines = content.split('\n');
        let currentTarget = null;
        lines.forEach(line => {
            line = line.trim();
            if (line.endsWith(')')) {
                currentTarget = line.slice(0, -1).trim();
                this.properties[currentTarget] = {};
            } else if (line.includes('=') && currentTarget) {
                const [key, value] = line.split('=');
                const trimmedKey = key.trim();
                if (trimmedKey.match(/targ_.*|NATIVE_LIB_DIRS/)) {
                    this.properties[currentTarget][trimmedKey] = value.trim().replace(/;;/g, '');
                }
            }
        });
    }

    printProperties() {
        console.log('Extracted Properties:');
        for (const target in this.properties) {
            console.log(`Target: ${target}`);
            for (const key in this.properties[target]) {
                console.log(`  ${key}: ${this.properties[target][key]}`);
            }
            console.log('');
        }
    }

    write(filename) {
        let content = '# Sample .TGT configuration script\n';
        content += 'targ_emul=\n';
        content += 'targ_extra_emuls=\n';
        content += 'targ_extra_libpath=\n';
        content += 'targ_extra_ofiles=\n';
        content += 'targ64_extra_emuls=\n';
        content += 'targ64_extra_libpath=\n';
        content += 'case "${targ}" in\n';
        for (const target in this.properties) {
            content += `  ${target})\n`;
            for (const key in this.properties[target]) {
                content += `    ${key}=${this.properties[target][key]} ;;\n`;
            }
        }
        content += '  *) echo "${targ} emulation unknown." ;;\n';
        content += 'esac\n';
        content += 'case "${targ_obj}" in\n';
        content += '# NATIVE_LIB_DIRS setting\n';
        content += 'esac\n';

        const blob = new Blob([content], {type: 'text/plain'});
        const url = URL.createObjectURL(blob);
        const a = document.createElement('a');
        a.href = url;
        a.download = filename;
        a.click();
        URL.revokeObjectURL(url);
    }
}

// Example usage (in browser console or script)
// const tgt = new TGTFile();
// tgt.read(someFileObject).then(() => tgt.printProperties());
// tgt.write('output.tgt');

7. C Class for .TGT File Handling

The following C++ class can open, decode (parse), read (extract properties), write (generate file from properties), and print the properties to console.

#include <iostream>
#include <fstream>
#include <sstream>
#include <map>
#include <string>
#include <regex>

class TGTFile {
private:
    std::map<std::string, std::map<std::string, std::string>> properties;

public:
    TGTFile(const std::string& filename = "") {
        if (!filename.empty()) {
            read(filename);
        }
    }

    void read(const std::string& filename) {
        std::ifstream file(filename);
        if (!file) {
            std::cerr << "Failed to open file." << std::endl;
            return;
        }
        std::stringstream buffer;
        buffer << file.rdbuf();
        parse(buffer.str());
    }

    void parse(const std::string& content) {
        properties.clear();
        std::istringstream iss(content);
        std::string line;
        std::string currentTarget;
        while (std::getline(iss, line)) {
            line.erase(0, line.find_first_not_of(" \t"));
            line.erase(line.find_last_not_of(" \t") + 1);
            if (line.back() == ')') {
                currentTarget = line.substr(0, line.size() - 1);
                currentTarget.erase(currentTarget.find_last_not_of(" \t") + 1);
                properties[currentTarget] = {};
            } else if (!line.empty() && line.find('=') != std::string::npos && !currentTarget.empty()) {
                size_t pos = line.find('=');
                std::string key = line.substr(0, pos);
                key.erase(key.find_last_not_of(" \t") + 1);
                std::string value = line.substr(pos + 1);
                value.erase(0, value.find_first_not_of(" \t"));
                value = std::regex_replace(value, std::regex(";;"), "");
                if (std::regex_match(key, std::regex("targ_.*|NATIVE_LIB_DIRS"))) {
                    properties[currentTarget][key] = value;
                }
            }
        }
    }

    void printProperties() const {
        for (const auto& targetPair : properties) {
            std::cout << "Target: " << targetPair.first << std::endl;
            for (const auto& propPair : targetPair.second) {
                std::cout << "  " << propPair.first << ": " << propPair.second << std::endl;
            }
            std::cout << std::endl;
        }
    }

    void write(const std::string& filename) const {
        std::ofstream file(filename);
        if (!file) {
            std::cerr << "Failed to write file." << std::endl;
            return;
        }
        file << "# Sample .TGT configuration script\n";
        file << "targ_emul=\n";
        file << "targ_extra_emuls=\n";
        file << "targ_extra_libpath=\n";
        file << "targ_extra_ofiles=\n";
        file << "targ64_extra_emuls=\n";
        file << "targ64_extra_libpath=\n";
        file << "case \"${targ}\" in\n";
        for (const auto& targetPair : properties) {
            file << "  " << targetPair.first << ")\n";
            for (const auto& propPair : targetPair.second) {
                file << "    " << propPair.first << "=" << propPair.second << " ;;\n";
            }
        }
        file << "  *) echo \"${targ} emulation unknown.\" ;;\n";
        file << "esac\n";
        file << "case \"${targ_obj}\" in\n";
        file << "# NATIVE_LIB_DIRS setting\n";
        file << "esac\n";
    }
};

// Example usage
int main() {
    TGTFile tgt("example.tgt");
    tgt.printProperties();
    tgt.write("output.tgt");
    return 0;
}