mirror of
https://github.com/NVIDIA/open-gpu-kernel-modules.git
synced 2026-04-21 14:59:19 +00:00
515.43.04
This commit is contained in:
187
src/common/uproc/os/libos-v2.0.0/debug/elf.c
Normal file
187
src/common/uproc/os/libos-v2.0.0/debug/elf.c
Normal file
@@ -0,0 +1,187 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2017-2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef NVRM
|
||||
|
||||
# include <nvport/nvport.h>
|
||||
# define memcpy(d, s, l) portMemCopy(d, l, s, l)
|
||||
# define strcmp(str1, str2) portStringCompare(str1, str2, 0x1000)
|
||||
|
||||
#else // NVRM
|
||||
|
||||
# include <memory.h>
|
||||
# include <stdio.h>
|
||||
# include <string.h>
|
||||
|
||||
#endif // NVRM
|
||||
|
||||
#include "elf.h"
|
||||
#include "nvtypes.h"
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Find the start and end of the ELF section in memory
|
||||
* from the section name.
|
||||
*
|
||||
* @param[in] elf
|
||||
* @param[in] sectionName
|
||||
* The section to find such as .text or .data
|
||||
* @param[out] start, end
|
||||
* The start and end of the section in the loaded ELF file
|
||||
* e.g validPtr >= start && validPtr < end
|
||||
* @param[out] va_baase
|
||||
* The virtual address this section is loaded at
|
||||
*/
|
||||
NvBool
|
||||
libosElfFindSectionByName(elf64_header *elf, const char *targetName, NvU8 **start, NvU8 **end, NvU64 *va_base)
|
||||
{
|
||||
elf64_shdr *shdr = (elf64_shdr *)(((char *)elf) + elf->shoff);
|
||||
const char *string_base = ((char *)elf) + shdr[elf->shstrndx].offset;
|
||||
NvU32 i;
|
||||
|
||||
for (i = 0; i < elf->shnum; i++, shdr++)
|
||||
{
|
||||
const char *name = string_base + shdr->name;
|
||||
if (strcmp(name, targetName) == 0)
|
||||
{
|
||||
*start = (NvU8 *)elf + shdr->offset;
|
||||
*end = (NvU8 *)elf + shdr->offset + shdr->size;
|
||||
*va_base = shdr->addr;
|
||||
return NV_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return NV_FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Find the start and end of the ELF section in memory
|
||||
* from the section name.
|
||||
*
|
||||
* @param[in] elf
|
||||
* @param[in] sectionName
|
||||
* The section to find such as .text or .data
|
||||
* @param[out] start, end
|
||||
* The start and end of the section in the loaded ELF file
|
||||
* e.g validPtr >= start && validPtr < end
|
||||
* @param[out] va_base
|
||||
* The virtual address this section is loaded at
|
||||
*/
|
||||
NvBool
|
||||
libosElfFindSectionByAddress(elf64_header *elf, NvU64 address, NvU8 **start, NvU8 **end, NvU64 *va_base)
|
||||
{
|
||||
elf64_shdr *shdr = (elf64_shdr *)(((char *)elf) + elf->shoff);
|
||||
NvU32 i;
|
||||
|
||||
for (i = 0; i < elf->shnum; i++, shdr++)
|
||||
{
|
||||
if (address >= shdr->addr && address < (shdr->addr + shdr->size))
|
||||
{
|
||||
*start = (NvU8 *)elf + shdr->offset;
|
||||
*end = (NvU8 *)elf + shdr->offset + shdr->size;
|
||||
*va_base = shdr->addr;
|
||||
return NV_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return NV_FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Reads an arbitrary sized block of memory by loaded VA through
|
||||
* the ELF. This can be used to read data from the perspective
|
||||
* of a processor who has loaded the ELF.
|
||||
*
|
||||
* @param[in] elf
|
||||
* @param[in] address
|
||||
* The absolute virtual address to read
|
||||
* @param[out] size
|
||||
* The number of bytes that must be valid.
|
||||
* @returns
|
||||
* The pointer to the data in question, or NULL if the operation failed)
|
||||
*/
|
||||
void *libosElfReadVirtual(elf64_header *elf, NvU64 address, NvU64 size)
|
||||
{
|
||||
NvU8 *start, *end;
|
||||
NvU64 va_base;
|
||||
NvU64 section_offset;
|
||||
NvU64 section_offset_tail;
|
||||
|
||||
// @todo This really should be using the PHDR as theoretically section headers
|
||||
// might be stripped
|
||||
if (!libosElfFindSectionByAddress(elf, address, &start, &end, &va_base))
|
||||
return 0;
|
||||
|
||||
section_offset = address - va_base;
|
||||
|
||||
// Compute section offset (overflow check)
|
||||
section_offset_tail = section_offset + size;
|
||||
if (section_offset_tail < section_offset)
|
||||
return 0;
|
||||
|
||||
// Bounds check the tail
|
||||
if (section_offset_tail > (NvLength)(end - start))
|
||||
return 0;
|
||||
|
||||
return (address - va_base) + start;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Reads an arbitrary length string by loaded VA through
|
||||
* the ELF. This can be used to read data from the perspective
|
||||
* of a processor who has loaded the ELF.
|
||||
*
|
||||
* @param[in] elf
|
||||
* @param[in] address
|
||||
* The absolute virtual address to read
|
||||
* @returns
|
||||
* The pointer to the data in question, or NULL if the operation failed)
|
||||
* Ensures that all bytes of the string lie within the ELF same section.
|
||||
*/
|
||||
const char *libosElfReadStringVirtual(elf64_header *elf, NvU64 address)
|
||||
{
|
||||
NvU8 *start, *end;
|
||||
NvU64 base;
|
||||
NvU8 *region;
|
||||
NvU8 *i;
|
||||
|
||||
// @todo This really should be using the PHDR as theoretically section headers
|
||||
// might be stripped
|
||||
if (!libosElfFindSectionByAddress(elf, address, &start, &end, &base))
|
||||
return 0;
|
||||
|
||||
region = (address - base) + start;
|
||||
i = region;
|
||||
|
||||
while (i >= start && i < end)
|
||||
{
|
||||
if (!*i)
|
||||
return (const char *)region;
|
||||
i++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
107
src/common/uproc/os/libos-v2.0.0/debug/elf.h
Normal file
107
src/common/uproc/os/libos-v2.0.0/debug/elf.h
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2017-2018 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef GSP_ELF_H_
|
||||
#define GSP_ELF_H_
|
||||
|
||||
#include <nvtypes.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Structures for Loader
|
||||
typedef struct
|
||||
{
|
||||
NvU8 ident[16];
|
||||
NvU16 type;
|
||||
NvU16 machine;
|
||||
NvU32 version;
|
||||
NvU64 entry;
|
||||
NvU64 phoff;
|
||||
NvU64 shoff;
|
||||
NvU32 flags;
|
||||
NvU16 ehsize;
|
||||
NvU16 phentsize;
|
||||
NvU16 phnum;
|
||||
NvU16 shentsize;
|
||||
NvU16 shnum;
|
||||
NvU16 shstrndx;
|
||||
} elf64_header;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NvU32 type;
|
||||
NvU32 flags;
|
||||
NvU64 offset;
|
||||
NvU64 vaddr;
|
||||
NvU64 paddr;
|
||||
NvU64 filesz;
|
||||
NvU64 memsz;
|
||||
NvU64 align;
|
||||
} elf64_phdr;
|
||||
|
||||
#define PF_X 1
|
||||
#define PF_W 2
|
||||
#define PF_R 4
|
||||
|
||||
#define PT_LOAD 1
|
||||
|
||||
// Structures for finding Symbols
|
||||
typedef struct
|
||||
{
|
||||
NvU32 name;
|
||||
NvU32 type;
|
||||
NvU64 flags;
|
||||
NvU64 addr;
|
||||
NvU64 offset;
|
||||
NvU64 size;
|
||||
NvU32 link;
|
||||
NvU32 info;
|
||||
NvU64 addralign;
|
||||
NvU64 entsize;
|
||||
} elf64_shdr;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NvU32 name;
|
||||
NvU8 info;
|
||||
NvU8 other;
|
||||
NvU16 shndx;
|
||||
NvU64 value;
|
||||
NvU64 size;
|
||||
} elf64_sym;
|
||||
|
||||
// Core ELF API
|
||||
NvBool libosElfFindSectionByName(
|
||||
elf64_header *elf, const char *sectionName, NvU8 **start, NvU8 **end, NvU64 *va_base);
|
||||
NvBool
|
||||
libosElfFindSectionByAddress(elf64_header *elf, NvU64 address, NvU8 **start, NvU8 **end, NvU64 *va_base);
|
||||
void *libosElfReadVirtual(elf64_header *elf, NvU64 address, NvU64 size);
|
||||
const char *libosElfReadStringVirtual(elf64_header *elf, NvU64 address);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
885
src/common/uproc/os/libos-v2.0.0/debug/lines.c
Normal file
885
src/common/uproc/os/libos-v2.0.0/debug/lines.c
Normal file
@@ -0,0 +1,885 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2017-2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifdef NVRM
|
||||
|
||||
# include <stddef.h>
|
||||
# include <nvport/nvport.h>
|
||||
# define printf(fmt, ...) nv_printf(LEVEL_ERROR, fmt, ##__VA_ARGS__)
|
||||
|
||||
#else // NVRM
|
||||
|
||||
# include <memory.h>
|
||||
# include <stdio.h>
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
|
||||
# define portMemCopy(d, l, s, m) memcpy(d, s, l)
|
||||
# define portMemSet(d, v, l) memset(d, v, l)
|
||||
# define portStringCompare(str1, str2, l) strcmp(str1, str2)
|
||||
# define portMemAllocNonPaged(l) malloc(l);
|
||||
# define portMemFree(p) free(p);
|
||||
|
||||
#endif // NVRM
|
||||
|
||||
#include "nvtypes.h"
|
||||
#include "lines.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const NvU8 *buffer;
|
||||
NvU64 offset;
|
||||
NvU64 size;
|
||||
} DwarfStream;
|
||||
|
||||
static void libosDwarfBuildTables(libosDebugResolver *pThis);
|
||||
static void dwarfBuildARangeTable(libosDebugResolver *pThis);
|
||||
static void dwarfSetARangeTableLineUnit(libosDebugResolver *pThis, DwarfStream unit, NvU64 address);
|
||||
|
||||
// http://www.dwarfstd.org/doc/dwarf-2.0.0.pdf
|
||||
|
||||
// Debug Line information related structures
|
||||
// (for branch history and call stacks)
|
||||
enum
|
||||
{
|
||||
DW_LNS_extended_operation = 0,
|
||||
DW_LNS_copy = 1,
|
||||
DW_LNS_advance_pc = 2,
|
||||
DW_LNS_advance_line = 3,
|
||||
DW_LNS_set_file = 4,
|
||||
DW_LNS_set_column = 5,
|
||||
DW_LNS_negate_stmt = 6,
|
||||
DW_LNS_set_basic_block = 7,
|
||||
DW_LNS_const_add_pc = 8,
|
||||
DW_LNS_fixed_advance_pc = 9,
|
||||
DW_LNS_set_prologue_end = 10,
|
||||
DW_LNS_set_epilogue_begin = 11,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
DW_LNE_end_sequence = 1,
|
||||
DW_LNE_set_address = 2,
|
||||
DW_LNE_define_file = 3,
|
||||
DW_LNE_set_discriminator = 4,
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Creates a resolver object for a given ELF.
|
||||
* No resources or memory are retained by this call.
|
||||
*
|
||||
* @param[in] elf
|
||||
* An elf containing .debug_line and or .symtab data
|
||||
* @param[in] pThis
|
||||
* An uninitialized resolver object.
|
||||
*/
|
||||
void libosDebugResolverConstruct(libosDebugResolver *pThis, elf64_header *elf)
|
||||
{
|
||||
NvU64 vabase;
|
||||
libosElfFindSectionByName(elf, ".debug_line", &pThis->debugLineStart, &pThis->debugLineEnd, &vabase);
|
||||
libosElfFindSectionByName(
|
||||
elf, ".debug_aranges", &pThis->debugARangesStart, &pThis->debugARangesEnd, &vabase);
|
||||
libosElfFindSectionByName(elf, ".symtab", &pThis->symtabStart, &pThis->symtabEnd, &vabase);
|
||||
libosElfFindSectionByName(elf, ".strtab", &pThis->strtabStart, &pThis->strtabEnd, &vabase);
|
||||
libosDwarfBuildTables(pThis);
|
||||
}
|
||||
|
||||
void libosDebugResolverDestroy(libosDebugResolver *pThis)
|
||||
{
|
||||
if (pThis->arangeTable != NULL)
|
||||
{
|
||||
portMemFree(pThis->arangeTable);
|
||||
pThis->arangeTable = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Helper method to resolve symbol name to VA
|
||||
*
|
||||
* @param[in] pThis
|
||||
* An initialized resolver object.
|
||||
* @param[in] symbolName
|
||||
* Name of a symbol (code or data) for lookup.
|
||||
* @param[out] address
|
||||
* The virtual address for the given symbol.\
|
||||
*/
|
||||
NvBool libosDebugResolveSymbolToVA(libosDebugResolver *pThis, const char *symbolName, NvU64 *address)
|
||||
{
|
||||
elf64_sym *i = (elf64_sym *)pThis->symtabStart;
|
||||
|
||||
NvU64 count = (pThis->symtabEnd - pThis->symtabStart) / sizeof(elf64_sym);
|
||||
while (count--)
|
||||
{
|
||||
if (i->name != 0)
|
||||
{
|
||||
if (!portStringCompare(i->name + (const char *)pThis->strtabStart, symbolName, 0x1000))
|
||||
{
|
||||
*address = i->value;
|
||||
return NV_TRUE;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return NV_FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Helper method to resolve symbol VA back to name
|
||||
* @note This will match on addresses within a sized symbol (!)
|
||||
*
|
||||
* @param[in] pThis
|
||||
* An initialized resolver object.
|
||||
* @param[in] symbolAddress
|
||||
* An address for which we want either
|
||||
* (1) The symbol that exactly resolves to this address
|
||||
* (2) The symbol that contains this address
|
||||
* @param[out] offset
|
||||
* Offsets are returned if the match is within a symbol.
|
||||
* @param[out] name
|
||||
* The symbol name containing or matching the search address
|
||||
*/
|
||||
NvBool libosDebugResolveSymbolToName(
|
||||
libosDebugResolver *pThis, NvU64 symbolAddress, const char **name, NvU64 *offset)
|
||||
{
|
||||
elf64_sym *i = (elf64_sym *)pThis->symtabStart;
|
||||
NvU64 count = (pThis->symtabEnd - pThis->symtabStart) / sizeof(elf64_sym);
|
||||
while (count--)
|
||||
{
|
||||
if (symbolAddress == i->value || (symbolAddress >= i->value && symbolAddress < i->value + i->size))
|
||||
{
|
||||
if (i->name)
|
||||
*name = i->name + (const char *)pThis->strtabStart;
|
||||
else
|
||||
*name = "";
|
||||
*offset = symbolAddress - i->value;
|
||||
return NV_TRUE;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return NV_FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Helper method to look up the symbol for a VA and return the VA range
|
||||
* that symbol covers.
|
||||
* @note This will match on addresses within a sized symbol (!)
|
||||
*
|
||||
* @param[in] pThis
|
||||
* An initialized resolver object.
|
||||
* @param[in] symbolAddress
|
||||
* An address for which we want either
|
||||
* (1) The symbol that exactly resolves to this address
|
||||
* (2) The symbol that contains this address
|
||||
* @param[out] symStart
|
||||
* First address covered by the symbol..
|
||||
* @param[out] symEnd
|
||||
* One past the last address covered by the symbol.
|
||||
*/
|
||||
NvBool libosDebugGetSymbolRange(
|
||||
libosDebugResolver *pThis, NvU64 symbolAddress, NvU64 *symStart, NvU64 *symEnd)
|
||||
{
|
||||
elf64_sym *i = (elf64_sym *)pThis->symtabStart;
|
||||
elf64_sym *symtabEnd = (elf64_sym *)pThis->symtabEnd;
|
||||
|
||||
for (; i < symtabEnd; i++)
|
||||
{
|
||||
if (symbolAddress == i->value ||
|
||||
((symbolAddress >= i->value) && (symbolAddress < i->value + i->size)))
|
||||
{
|
||||
*symStart = i->value;
|
||||
*symEnd = i->value + i->size;
|
||||
return NV_TRUE;
|
||||
}
|
||||
}
|
||||
return NV_FALSE;
|
||||
}
|
||||
|
||||
static NvBool libosDwarfReadRaw(DwarfStream *stream, void *buffer, NvU64 size)
|
||||
{
|
||||
NvU64 newOffset = stream->offset + size;
|
||||
if (newOffset > stream->size)
|
||||
return NV_FALSE;
|
||||
portMemCopy(buffer, (size_t)size, stream->buffer + stream->offset, size);
|
||||
stream->offset = newOffset;
|
||||
return NV_TRUE;
|
||||
}
|
||||
|
||||
static NvBool libosDwarfExtractString(DwarfStream *stream, const char **string)
|
||||
{
|
||||
NvU64 offsetEnd = stream->offset;
|
||||
while (1)
|
||||
{
|
||||
if (offsetEnd >= stream->size)
|
||||
return NV_FALSE;
|
||||
if (!stream->buffer[offsetEnd])
|
||||
break;
|
||||
offsetEnd++;
|
||||
}
|
||||
|
||||
*string = (const char *)stream->buffer + stream->offset;
|
||||
stream->offset = offsetEnd + 1;
|
||||
|
||||
return NV_TRUE;
|
||||
}
|
||||
|
||||
#define DWARF_READ(stream, ptr) libosDwarfReadRaw(stream, ptr, sizeof(*ptr))
|
||||
|
||||
static NvBool dwarfReadLeb128Generic(DwarfStream *stream, NvU64 *presult, NvBool sextension)
|
||||
{
|
||||
NvU8 byte;
|
||||
NvU64 bitsRead = 0, result = 0;
|
||||
while (bitsRead < 64 && DWARF_READ(stream, &byte))
|
||||
{
|
||||
// Read 7 bits
|
||||
result |= (NvU64)(byte & 0x7f) << bitsRead;
|
||||
bitsRead += 7;
|
||||
|
||||
// Was this the last byte?
|
||||
if (!(byte & 0x80))
|
||||
{
|
||||
// Sign extend based on the top bit we just read
|
||||
if (sextension && bitsRead < 64 && (byte & 0x40))
|
||||
result |= 0xFFFFFFFFFFFFFFFFULL << bitsRead;
|
||||
|
||||
// Return result
|
||||
*presult = result;
|
||||
return NV_TRUE;
|
||||
}
|
||||
}
|
||||
return NV_FALSE;
|
||||
}
|
||||
|
||||
static NvBool dwarfReadSleb128(DwarfStream *stream, NvS64 *result)
|
||||
{
|
||||
return dwarfReadLeb128Generic(stream, (NvU64 *)result, NV_TRUE /* sign extend */);
|
||||
}
|
||||
|
||||
static NvBool dwarfReadUleb128(DwarfStream *stream, NvU64 *result)
|
||||
{
|
||||
return dwarfReadLeb128Generic(stream, result, NV_FALSE);
|
||||
}
|
||||
|
||||
static NvBool dwarfReadFilename(DwarfStream *names, const char **directory, const char **filename, NvU64 file)
|
||||
{
|
||||
// Skip the directory names stream
|
||||
DwarfStream dirnames = *names;
|
||||
const char *name;
|
||||
|
||||
NvU64 directoryEntryId = 0;
|
||||
NvU64 i;
|
||||
|
||||
*directory = "";
|
||||
*filename = "";
|
||||
|
||||
if (!file)
|
||||
return NV_FALSE;
|
||||
|
||||
do
|
||||
{
|
||||
if (!libosDwarfExtractString(names, &name))
|
||||
return (NV_FALSE);
|
||||
} while (*name);
|
||||
|
||||
// Walk through the file entries
|
||||
for (i = 0; i < file; i++)
|
||||
{
|
||||
NvU64 mtime, size;
|
||||
if (!libosDwarfExtractString(names, filename) || !dwarfReadUleb128(names, &directoryEntryId) ||
|
||||
!dwarfReadUleb128(names, &mtime) || !dwarfReadUleb128(names, &size))
|
||||
return NV_FALSE;
|
||||
}
|
||||
|
||||
// Walk the directory table up until the required point
|
||||
for (i = 0; i < directoryEntryId; i++)
|
||||
if (!libosDwarfExtractString(&dirnames, directory))
|
||||
return NV_FALSE;
|
||||
|
||||
return NV_TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief DWARF-2 Virtual machine interpreter for debug data
|
||||
*
|
||||
* @param[in] pThis
|
||||
* An initialized resolver object.
|
||||
* @param[in/out] unit
|
||||
* A dwarf stream object initialized to the start of a unit in the
|
||||
* .debug_lines elf section.
|
||||
* @param[in] pc
|
||||
* Virtual address of the code to resolve.
|
||||
* @param[out] directory
|
||||
* The source file directory for this line of code. Requires a .debug_line section.
|
||||
* @param[out] filename
|
||||
* The source file for this line of code. Requires a .debug_line section.
|
||||
* @param[out] outputLine
|
||||
* The source line for address. Requires a .debug_line section.
|
||||
* @param[out] outputColumn
|
||||
* The source column for this address. Requires additional debug info -g3.
|
||||
* @param[in] matchedAddress
|
||||
* Returns the virtual address to the start of the matched line/col.
|
||||
* @param[in] bBuildTable
|
||||
* Set to true when building the aranges index table.
|
||||
*/
|
||||
static NvBool dwarfParseUnitLines(
|
||||
libosDebugResolver *pThis, DwarfStream unit, NvU64 pc, const char **directory, const char **filename,
|
||||
NvU64 *outputLine, NvU64 *outputColumn, NvU64 *matchedAddress, NvBool bBuildTable)
|
||||
{
|
||||
NvU16 version;
|
||||
NvU32 prologueLength;
|
||||
|
||||
DwarfStream saveUnit = unit;
|
||||
|
||||
NvU64 headerOffset;
|
||||
NvU8 minimumInstructionLength, defaultIsStmt, lineRange, opcodeBase;
|
||||
NvS8 line_base;
|
||||
NvU64 i;
|
||||
|
||||
DwarfStream names;
|
||||
|
||||
// Initial state of virtual machine
|
||||
NvU64 previousAddress = 0, previousLine = 0, previousColumn = 0, previousFile = 0;
|
||||
NvU64 address = 0, file = 1, line = 1, column = 0;
|
||||
NvU8 isStmt;
|
||||
//NvBool basicBlock = NV_FALSE
|
||||
NvBool postEmitResetState = NV_FALSE;
|
||||
//NvBool prologueEnd = NV_FALSE;
|
||||
//NvBool epilogueBegin = NV_FALSE;
|
||||
NvBool postEmitResetStateIsStmt = NV_FALSE;
|
||||
//NvBool endSequence = NV_FALSE;
|
||||
NvU8 opcode;
|
||||
|
||||
if (!DWARF_READ(&unit, &version) || version > 2 || !DWARF_READ(&unit, &prologueLength))
|
||||
{
|
||||
return NV_FALSE;
|
||||
}
|
||||
|
||||
headerOffset = unit.offset;
|
||||
if (!DWARF_READ(&unit, &minimumInstructionLength) || !DWARF_READ(&unit, &defaultIsStmt) ||
|
||||
!DWARF_READ(&unit, &line_base) || !DWARF_READ(&unit, &lineRange) || !DWARF_READ(&unit, &opcodeBase))
|
||||
{
|
||||
return NV_FALSE;
|
||||
}
|
||||
|
||||
// Skip over the opcode lengths
|
||||
for (i = 1; i < opcodeBase; i++)
|
||||
{
|
||||
NvU64 dummy;
|
||||
if (!dwarfReadUleb128(&unit, &dummy))
|
||||
{
|
||||
return NV_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
// Names section starts here inside after the prologue
|
||||
names = unit;
|
||||
|
||||
// Skip prologue
|
||||
unit.offset = headerOffset;
|
||||
if (unit.size - unit.offset < prologueLength)
|
||||
{
|
||||
//printf("Bailing 3...\n");
|
||||
return NV_FALSE;
|
||||
}
|
||||
unit.offset += prologueLength;
|
||||
|
||||
isStmt = defaultIsStmt;
|
||||
|
||||
// Run the line number information program for this unit
|
||||
while (NV_TRUE)
|
||||
{
|
||||
NvBool emit_row = NV_FALSE;
|
||||
|
||||
//NvU64 offset = unit.offset;
|
||||
if (!DWARF_READ(&unit, &opcode))
|
||||
break;
|
||||
//NvBool reset_basic_block = NV_FALSE;
|
||||
|
||||
// 6.2.5.1 Special Opcodes
|
||||
if (opcode >= opcodeBase)
|
||||
{
|
||||
NvU8 normalizedOpcode = opcode - opcodeBase;
|
||||
address += (normalizedOpcode / lineRange) * minimumInstructionLength;
|
||||
line += line_base + normalizedOpcode % lineRange;
|
||||
//reset_basic_block = NV_TRUE;
|
||||
emit_row = NV_TRUE;
|
||||
//printf(" [0x%08llx] Special opcode\n", offset);
|
||||
}
|
||||
// 6.2.5.3 Extended Opcodes
|
||||
else if (opcode == DW_LNS_extended_operation)
|
||||
{
|
||||
NvU64 extBaseOffset = unit.offset, extraSize;
|
||||
DwarfStream extra;
|
||||
|
||||
if (!dwarfReadUleb128(&unit, &extraSize))
|
||||
return NV_FALSE;
|
||||
|
||||
if (unit.size - unit.offset < extraSize)
|
||||
return NV_FALSE;
|
||||
extra.buffer = unit.buffer + extBaseOffset;
|
||||
extra.offset = unit.offset - extBaseOffset;
|
||||
extra.size = extraSize + unit.offset - extBaseOffset;
|
||||
unit.offset += extraSize;
|
||||
|
||||
if (!DWARF_READ(&extra, &opcode))
|
||||
return NV_FALSE;
|
||||
|
||||
switch (opcode)
|
||||
{
|
||||
case DW_LNE_end_sequence:
|
||||
emit_row = NV_TRUE;
|
||||
postEmitResetStateIsStmt = isStmt;
|
||||
postEmitResetState = NV_TRUE;
|
||||
//printf(" [0x%08llx] Extended opcode 1: End of Sequence\n", offset);
|
||||
break;
|
||||
|
||||
case DW_LNE_set_address:
|
||||
switch (extra.size - extra.offset)
|
||||
{
|
||||
case 8:
|
||||
if (!DWARF_READ(&extra, &address))
|
||||
return NV_FALSE;
|
||||
break;
|
||||
|
||||
case 4: {
|
||||
NvU32 address32;
|
||||
if (!DWARF_READ(&extra, &address32))
|
||||
return NV_FALSE;
|
||||
address = address32;
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
//printf("unexpected address length: %zu", extra.size - extra.offset);
|
||||
return NV_FALSE;
|
||||
}
|
||||
//printf(" [0x%08llx] Extended opcode 2: set Address to 0x%llx\n", offset, address);
|
||||
break;
|
||||
|
||||
case DW_LNE_define_file: {
|
||||
const char *fname = "";
|
||||
NvU64 dir, time, size;
|
||||
libosDwarfExtractString(&unit, &fname);
|
||||
//printf(" [0x%08x] Define file: %s\n", fname, offset);
|
||||
dwarfReadUleb128(&unit, &dir);
|
||||
dwarfReadUleb128(&unit, &time);
|
||||
dwarfReadUleb128(&unit, &size);
|
||||
}
|
||||
break;
|
||||
|
||||
case DW_LNE_set_discriminator: // For profilers, how many code paths pass through this insn
|
||||
{
|
||||
NvU64 discriminator;
|
||||
dwarfReadUleb128(&extra, &discriminator);
|
||||
//printf(" [0x%08llx] Extended opcode 4: set Discriminator to %lld\n", offset, discriminator);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
//printf(" [0x%08llx] unknown extended opcode: %d\n", offset, opcode);
|
||||
return NV_FALSE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* "Standard" opcodes. */
|
||||
switch (opcode)
|
||||
{
|
||||
case DW_LNS_copy:
|
||||
emit_row = NV_TRUE;
|
||||
//reset_basic_block = NV_TRUE;
|
||||
//printf(" [0x%08llx] Copy\n", offset);
|
||||
break;
|
||||
|
||||
case DW_LNS_advance_pc: {
|
||||
NvU64 delta;
|
||||
if (!dwarfReadUleb128(&unit, &delta))
|
||||
return NV_FALSE;
|
||||
address += delta * minimumInstructionLength;
|
||||
//printf(" [0x%08llx] Advance PC by %lld to 0x%llx\n", offset, delta, address);
|
||||
break;
|
||||
}
|
||||
|
||||
case DW_LNS_fixed_advance_pc: {
|
||||
NvU16 delta = 0;
|
||||
DWARF_READ(&unit, &delta);
|
||||
address += delta * minimumInstructionLength;
|
||||
//printf(" [0x%08llx] Advance PC by fixed size amount %d to 0x%llx\n",offset , delta, address);
|
||||
break;
|
||||
}
|
||||
|
||||
case DW_LNS_advance_line: {
|
||||
NvS64 delta;
|
||||
if (!dwarfReadSleb128(&unit, &delta))
|
||||
return NV_FALSE;
|
||||
line += delta;
|
||||
//printf(" [0x%08llx] Advance Line by %lld to %lld\n", offset, delta, line);
|
||||
break;
|
||||
}
|
||||
|
||||
case DW_LNS_set_file:
|
||||
if (!dwarfReadUleb128(&unit, &file))
|
||||
return NV_FALSE;
|
||||
//printf(" [0x%08llx] Set File Name to entry %lld in the File Name Table\n", offset, file);
|
||||
break;
|
||||
|
||||
case DW_LNS_set_column:
|
||||
if (!dwarfReadUleb128(&unit, &column))
|
||||
return NV_FALSE;
|
||||
//printf(" [0x%08llx] Set column to %lld\n", offset, column);
|
||||
break;
|
||||
|
||||
case DW_LNS_negate_stmt:
|
||||
isStmt = !isStmt;
|
||||
//printf(" [0x%08llx] Set isStmt to %d\n", offset, isStmt);
|
||||
break;
|
||||
|
||||
case DW_LNS_set_basic_block:
|
||||
//basicBlock = NV_TRUE;
|
||||
//printf(" [0x%08llx] Set basic block\n", offset);
|
||||
break;
|
||||
|
||||
case DW_LNS_const_add_pc: {
|
||||
NvU64 delta = ((255 - opcodeBase) / lineRange) * minimumInstructionLength;
|
||||
address += delta;
|
||||
//printf(" [0x%08llx] Add pc by %lld to %08llx\n", offset, delta, address);
|
||||
break;
|
||||
}
|
||||
|
||||
case DW_LNS_set_prologue_end:
|
||||
//printf(" [0x%08llx] Set prologue end\n", offset);
|
||||
//prologueEnd = NV_TRUE;
|
||||
break;
|
||||
|
||||
case DW_LNS_set_epilogue_begin:
|
||||
//printf(" [0x%08llx] Set epilogie begin\n", offset);
|
||||
//epilogueBegin = NV_TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
//printf(" [0x%08llx] unknown standard opcode: %d\n", offset, opcode);
|
||||
return NV_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (emit_row)
|
||||
{
|
||||
if (bBuildTable)
|
||||
{
|
||||
dwarfSetARangeTableLineUnit(pThis, saveUnit, address);
|
||||
return NV_FALSE;
|
||||
}
|
||||
|
||||
if ((previousAddress && (pc >= previousAddress && pc < address)))
|
||||
{
|
||||
dwarfReadFilename(&names, directory, filename, previousFile);
|
||||
*outputLine = previousLine;
|
||||
*outputColumn = previousColumn;
|
||||
*matchedAddress = pc;
|
||||
return NV_TRUE;
|
||||
}
|
||||
|
||||
previousAddress = address;
|
||||
previousFile = file;
|
||||
previousLine = line;
|
||||
previousColumn = column;
|
||||
}
|
||||
|
||||
if (postEmitResetState)
|
||||
{
|
||||
address = 0;
|
||||
file = 1;
|
||||
line = 1;
|
||||
column = 0;
|
||||
isStmt = postEmitResetStateIsStmt;
|
||||
//basicBlock = NV_FALSE;
|
||||
postEmitResetState = NV_FALSE;
|
||||
//endSequence = NV_FALSE;
|
||||
//prologueEnd = NV_FALSE;
|
||||
//epilogueBegin = NV_FALSE;
|
||||
}
|
||||
|
||||
//if (reset_basic_block)
|
||||
// basicBlock = NV_FALSE;
|
||||
}
|
||||
return NV_FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Resolve an address to source file and line location for DWARF-2
|
||||
*
|
||||
* @param[in] pThis
|
||||
* An initialized resolver object.
|
||||
* @param[in] address
|
||||
* Virtual address of the code to resolve.
|
||||
* @param[out] filename
|
||||
* The source file for this line of code. Requires a .debug_line section.
|
||||
* @param[out] outputLine
|
||||
* The source line for address. Requires a .debug_line section.
|
||||
* @param[out] outputColumn
|
||||
* The source column for this address. Requires additional debug info -g3.
|
||||
* @param[in] matchedAddress
|
||||
* Returns the virtual address to the start of the matched line/col.
|
||||
*/
|
||||
NvBool libosDwarfResolveLine(
|
||||
libosDebugResolver *pThis, NvU64 address, const char **directory, const char **filename,
|
||||
NvU64 *outputLine, NvU64 *outputColumn, NvU64 *matchedAddress)
|
||||
{
|
||||
ARangeTupple *pFoundARange = NULL;
|
||||
DwarfStream unit;
|
||||
NvU32 i;
|
||||
|
||||
// Find entry in aranges table
|
||||
for (i = 0; i < pThis->nARangeEntries; i++)
|
||||
{
|
||||
if ((address >= pThis->arangeTable[i].address) &&
|
||||
(address < pThis->arangeTable[i].address + pThis->arangeTable[i].length))
|
||||
{
|
||||
pFoundARange = &pThis->arangeTable[i];
|
||||
|
||||
if (pFoundARange->lineUnitBuffer != NULL)
|
||||
{
|
||||
// Found cached line into in ARange table.
|
||||
unit.buffer = pFoundARange->lineUnitBuffer;
|
||||
unit.offset = 0;
|
||||
unit.size = pFoundARange->lineUnitSize;
|
||||
|
||||
if (dwarfParseUnitLines(
|
||||
pThis, unit, address, directory, filename, outputLine, outputColumn, matchedAddress,
|
||||
NV_FALSE))
|
||||
{
|
||||
return NV_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NV_FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Create a table indexing the units in .debug_line elf section
|
||||
*
|
||||
*
|
||||
* @param[in/out] pThis
|
||||
* An initialized resolver object.
|
||||
*/
|
||||
static void libosDwarfBuildTables(libosDebugResolver *pThis)
|
||||
{
|
||||
NvU32 tableSize;
|
||||
DwarfStream debugLines;
|
||||
DwarfStream unit;
|
||||
NvU32 currentUnit = 1;
|
||||
NvU32 unitSize;
|
||||
|
||||
pThis->arangeTable = NULL;
|
||||
pThis->nARangeEntries = 0;
|
||||
|
||||
// Run through the .debug_aranges elf section to get a count of consolidated ranges.
|
||||
dwarfBuildARangeTable(pThis);
|
||||
|
||||
tableSize = (pThis->nARangeEntries + 1) * sizeof(ARangeTupple);
|
||||
|
||||
// Allocate the table.
|
||||
pThis->arangeTable = portMemAllocNonPaged(tableSize);
|
||||
portMemSet(pThis->arangeTable, 0, tableSize);
|
||||
|
||||
// Run through the .debug_aranges elf section again to populate the table.
|
||||
dwarfBuildARangeTable(pThis);
|
||||
|
||||
debugLines.buffer = pThis->debugLineStart; debugLines.offset = 0; debugLines.size = pThis->debugLineEnd - pThis->debugLineStart;
|
||||
|
||||
// Run through the .debug_line elf section to match units to the arange table.
|
||||
for (currentUnit = 1;; currentUnit++)
|
||||
{
|
||||
if (!DWARF_READ(&debugLines, &unitSize) || unitSize >= 0xfffffff0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (debugLines.size - debugLines.offset < unitSize)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
unit.buffer = debugLines.buffer + debugLines.offset;
|
||||
unit.offset = 0;
|
||||
unit.size = unitSize;
|
||||
|
||||
dwarfParseUnitLines(pThis, unit, 0, NULL, NULL, NULL, NULL, NULL, NV_TRUE);
|
||||
debugLines.offset += unitSize;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Walk the .debug_aranges elf section, consolidate adjacent ranges,
|
||||
* and create a table with an entry for each range.
|
||||
*
|
||||
* @param[in/out] pThis
|
||||
* An initialized resolver object.
|
||||
*/
|
||||
static void dwarfBuildARangeTable(libosDebugResolver *pThis)
|
||||
{
|
||||
DwarfStream debugARanges = {
|
||||
pThis->debugARangesStart, 0, pThis->debugARangesEnd - pThis->debugARangesStart};
|
||||
DwarfStream unit;
|
||||
NvU32 nUnit = 0;
|
||||
NvU32 nARangeEntries = 0;
|
||||
|
||||
for (nUnit = 1;; nUnit++)
|
||||
{
|
||||
NvU32 unit_size = 0xffffffff;
|
||||
NvU32 debugInfoOffset = 0xffffffff;
|
||||
NvU16 version = 0xffff;
|
||||
NvU8 addressSize = 0xff;
|
||||
NvU8 selectorSize = 0xff;
|
||||
|
||||
NvU32 nUnitTupples;
|
||||
NvU64 combAddress = 0;
|
||||
NvU64 combLength = 0;
|
||||
|
||||
if (!DWARF_READ(&debugARanges, &unit_size) || unit_size >= 0xfffffff0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (debugARanges.size - debugARanges.offset < unit_size)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
unit.buffer = debugARanges.buffer + debugARanges.offset - sizeof unit_size;
|
||||
unit.offset = sizeof unit_size;
|
||||
unit.size = unit_size + sizeof unit_size;
|
||||
debugARanges.offset += unit_size;
|
||||
|
||||
if (!DWARF_READ(&unit, &version) || version != 2 || !DWARF_READ(&unit, &debugInfoOffset) ||
|
||||
!DWARF_READ(&unit, &addressSize) || !DWARF_READ(&unit, &selectorSize) || addressSize != 8 ||
|
||||
selectorSize != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
// Pad to natural alignment
|
||||
unit.offset = (unit.offset + 15) & ~15;
|
||||
|
||||
for (nUnitTupples = 0;; nUnitTupples++)
|
||||
{
|
||||
NvU64 address;
|
||||
NvU64 length;
|
||||
|
||||
if (!DWARF_READ(&unit, &address) || !DWARF_READ(&unit, &length))
|
||||
{
|
||||
address = 0;
|
||||
length = 0;
|
||||
}
|
||||
|
||||
if (address == combAddress + combLength)
|
||||
{
|
||||
combLength += length;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (combAddress != 0 && combLength != 0)
|
||||
{
|
||||
if (pThis->arangeTable != NULL && nARangeEntries < pThis->nARangeEntries)
|
||||
{
|
||||
// Table has been allocated -- fill it in.
|
||||
ARangeTupple *pEntry = &pThis->arangeTable[nARangeEntries];
|
||||
pEntry->address = combAddress;
|
||||
pEntry->length = (NvU32)combLength;
|
||||
pEntry->arangeUnit = nUnit;
|
||||
}
|
||||
nARangeEntries++;
|
||||
}
|
||||
|
||||
combAddress = address;
|
||||
combLength = length;
|
||||
}
|
||||
|
||||
if (address == 0 && length == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
pThis->nARangeEntries = nARangeEntries;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @brief Set a .debug_line reference in the table of consolidated aranges.
|
||||
*
|
||||
* @param[in] pThis
|
||||
* An initialized resolver object.
|
||||
* @param[in/out] unit
|
||||
* A dwarf stream object initialized to the start of a unit in the
|
||||
* .debug_lines elf section.
|
||||
* @param[in] address
|
||||
* Any virtual address contained in teh above .debug_lines unit.
|
||||
*/
|
||||
static void dwarfSetARangeTableLineUnit(libosDebugResolver *pThis, DwarfStream unit, NvU64 address)
|
||||
{
|
||||
NvU32 foundUnit = 0;
|
||||
NvU32 i;
|
||||
|
||||
// Find entry in aranges table
|
||||
for (i = 0; i < pThis->nARangeEntries; i++)
|
||||
{
|
||||
if ((address >= pThis->arangeTable[i].address) &&
|
||||
(address < pThis->arangeTable[i].address + pThis->arangeTable[i].length))
|
||||
{
|
||||
foundUnit = pThis->arangeTable[i].arangeUnit;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (foundUnit == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// Walk backwards to first table entry with the same areange unit.
|
||||
// Just in case -- I think i should always point to the first unit entry.
|
||||
//
|
||||
while ((i > 0) && (foundUnit == pThis->arangeTable[i - 1].arangeUnit))
|
||||
{
|
||||
i--;
|
||||
}
|
||||
|
||||
// Walk forwards setting the line unit info for all entries with the same arange unit.
|
||||
for (; (foundUnit == pThis->arangeTable[i].arangeUnit); i++)
|
||||
{
|
||||
pThis->arangeTable[i].lineUnitBuffer = unit.buffer;
|
||||
pThis->arangeTable[i].lineUnitSize = (NvU32)unit.size;
|
||||
}
|
||||
}
|
||||
62
src/common/uproc/os/libos-v2.0.0/debug/lines.h
Normal file
62
src/common/uproc/os/libos-v2.0.0/debug/lines.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2017-2020 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef LINES_H_
|
||||
#define LINES_H_
|
||||
|
||||
#include "elf.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NvU64 address;
|
||||
NvU32 length;
|
||||
NvU32 arangeUnit;
|
||||
const NvU8 *lineUnitBuffer;
|
||||
NvU32 lineUnitSize;
|
||||
|
||||
} ARangeTupple;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NvU8 *debugLineStart, *debugLineEnd;
|
||||
NvU8 *debugARangesStart, *debugARangesEnd;
|
||||
NvU8 *symtabStart, *symtabEnd;
|
||||
NvU8 *strtabStart, *strtabEnd;
|
||||
ARangeTupple *arangeTable;
|
||||
NvU32 nARangeEntries;
|
||||
} libosDebugResolver;
|
||||
|
||||
void libosDebugResolverConstruct(libosDebugResolver *pThis, elf64_header *elf);
|
||||
void libosDebugResolverDestroy(libosDebugResolver *pThis);
|
||||
|
||||
// @note Optimized for single lookup (no search structures are created)
|
||||
NvBool libosDebugResolveSymbolToVA(libosDebugResolver *pThis, const char *symbol, NvU64 *address);
|
||||
NvBool libosDebugResolveSymbolToName(
|
||||
libosDebugResolver *pThis, NvU64 symbolAddress, const char **name, NvU64 *offset);
|
||||
NvBool libosDwarfResolveLine(
|
||||
libosDebugResolver *pThis, NvU64 address, const char **directory, const char **filename,
|
||||
NvU64 *outputLine, NvU64 *outputColumn, NvU64 *matchedAddress);
|
||||
NvBool libosDebugGetSymbolRange(
|
||||
libosDebugResolver *pThis, NvU64 symbolAddress, NvU64 *symStart, NvU64 *symEnd);
|
||||
|
||||
#endif
|
||||
1390
src/common/uproc/os/libos-v2.0.0/debug/logdecode.c
Normal file
1390
src/common/uproc/os/libos-v2.0.0/debug/logdecode.c
Normal file
File diff suppressed because it is too large
Load Diff
177
src/common/uproc/os/libos-v2.0.0/debug/logdecode.h
Normal file
177
src/common/uproc/os/libos-v2.0.0/debug/logdecode.h
Normal file
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2019-2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef LOGDECODE_H_
|
||||
#define LOGDECODE_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef NVRM
|
||||
|
||||
# define LIBOS_LOG_DECODE_ENABLE 1
|
||||
|
||||
# define LIBOS_LOG_TO_NVLOG 1
|
||||
|
||||
# define LIBOS_LOG_MAX_LOGS 5 // Max logs per GPU
|
||||
|
||||
#else // NVRM
|
||||
# include <stdio.h>
|
||||
|
||||
# define LIBOS_LOG_DECODE_ENABLE 1
|
||||
# define LIBOS_LOG_TO_NVLOG 0
|
||||
|
||||
# define LIBOS_LOG_MAX_LOGS 160 // Max logs for all GPUs for offline decoder
|
||||
|
||||
#endif // NVRM
|
||||
|
||||
#define LIBOS_LOG_ENABLE (LIBOS_LOG_TO_NVLOG || LIBOS_LOG_DECODE_ENABLE)
|
||||
|
||||
#if LIBOS_LOG_DECODE_ENABLE
|
||||
# include "../include/libos_log.h"
|
||||
# include "lines.h"
|
||||
#endif
|
||||
|
||||
// Forward declarations.
|
||||
struct LIBOS_LOG_DECODE_LOG;
|
||||
typedef struct LIBOS_LOG_DECODE_LOG LIBOS_LOG_DECODE_LOG;
|
||||
|
||||
#define LIBOS_LOG_LINE_BUFFER_SIZE 128
|
||||
#define LIBOS_LOG_MAX_ARGS 20
|
||||
|
||||
#if LIBOS_LOG_DECODE_ENABLE
|
||||
|
||||
# include "nvctassert.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
NV_DECLARE_ALIGNED(LIBOS_LOG_DECODE_LOG *log, 8);
|
||||
NV_DECLARE_ALIGNED(libosLogMetadata *meta, 8);
|
||||
NV_DECLARE_ALIGNED(NvU64 timeStamp, 8);
|
||||
NvU64 args[LIBOS_LOG_MAX_ARGS];
|
||||
} LIBOS_LOG_DECODE_RECORD;
|
||||
|
||||
// Size of LIBOS_LOG_DECODE_RECORD without args, in number of NvU64 entries.
|
||||
# define LIBOS_LOG_DECODE_RECORD_BASE 3
|
||||
|
||||
// Ensure that the size matches up (no padding in the struct)
|
||||
ct_assert((LIBOS_LOG_DECODE_RECORD_BASE * sizeof(NvU64)) == (sizeof(LIBOS_LOG_DECODE_RECORD) - sizeof(((LIBOS_LOG_DECODE_RECORD*)NULL)->args)));
|
||||
|
||||
#endif // LIBOS_LOG_DECODE_ENABLE
|
||||
|
||||
#define TASK_NAME_MAX_LENGTH (8)
|
||||
#define SOURCE_NAME_MAX_LENGTH (4)
|
||||
|
||||
// NvLog buffer
|
||||
typedef struct
|
||||
{
|
||||
NvU32 gpuArch;
|
||||
NvU32 gpuImpl;
|
||||
NvU32 rsvd1;
|
||||
NvU32 rsvd2;
|
||||
char taskPrefix[TASK_NAME_MAX_LENGTH]; // Prefix string printed before each line.
|
||||
NvU8 data[0];
|
||||
} LIBOS_LOG_NVLOG_BUFFER;
|
||||
|
||||
struct LIBOS_LOG_DECODE_LOG
|
||||
{
|
||||
volatile NvU64 *physicLogBuffer;
|
||||
NvU64 logBufferSize; // Includes put pointer located in first 8 bytes.
|
||||
NvU64 previousPut; // Keeps track of records already printed.
|
||||
NvU64 putCopy; // End pointer for this batch.
|
||||
NvU64 putIter; // Iterator for this batch.
|
||||
NvU32 gpuInstance; // GPU that this log is associated with.
|
||||
char taskPrefix[TASK_NAME_MAX_LENGTH]; // Prefix string printed before each line.
|
||||
|
||||
#if LIBOS_LOG_TO_NVLOG
|
||||
NvU32 hNvLogNoWrap; // No wrap buffer captures first records.
|
||||
NvU32 hNvLogWrap; // Wrap buffer captures last records.
|
||||
NvBool bNvLogNoWrap; // NV_TRUE if no wrap buffer not full.
|
||||
#endif
|
||||
|
||||
#if LIBOS_LOG_DECODE_ENABLE
|
||||
LIBOS_LOG_DECODE_RECORD record;
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char sourceName[SOURCE_NAME_MAX_LENGTH]; // GSP, PMU etc
|
||||
|
||||
NvU64 numLogBuffers;
|
||||
LIBOS_LOG_DECODE_LOG log[LIBOS_LOG_MAX_LOGS];
|
||||
|
||||
#if LIBOS_LOG_DECODE_ENABLE
|
||||
elf64_header *elf;
|
||||
libosDebugResolver resolver;
|
||||
NvU64 *scratchBuffer; // Sorted by timestamp.
|
||||
NvU64 scratchBufferSize; // Sum of logBufferSize.
|
||||
char *curLineBufPtr; // Current position in lineBuffer.
|
||||
// Decodes into lineBuffer, then prints as a string.
|
||||
char lineBuffer[LIBOS_LOG_LINE_BUFFER_SIZE];
|
||||
NvBool bSynchronousBuffer;
|
||||
NvBool bPtrSymbolResolve;
|
||||
#endif // LIBOS_LOG_DECODE_ENABLE
|
||||
|
||||
#if defined(NVSYM_STANDALONE) && !defined(PROTODMP_BUILD)
|
||||
FILE *fout; // nvlog_decoder outputs to FILE descriptors
|
||||
#elif defined(NVWATCH)
|
||||
char *dest; // nvwatch dumps data into a string
|
||||
#endif
|
||||
|
||||
} LIBOS_LOG_DECODE;
|
||||
|
||||
#if defined(NVSYM_STANDALONE) && !defined(PROTODMP_BUILD)
|
||||
void libosLogCreate(LIBOS_LOG_DECODE *logDecode, FILE *fout);
|
||||
void libosLogCreateEx(LIBOS_LOG_DECODE *logDecode, const char *pSourceName, FILE *fout);
|
||||
#elif defined(NVWATCH)
|
||||
void libosLogCreate(LIBOS_LOG_DECODE *logDecode, char *dest);
|
||||
void libosLogCreateEx(LIBOS_LOG_DECODE *logDecode, const char *pSourceName, char *dest);
|
||||
#else
|
||||
void libosLogCreate(LIBOS_LOG_DECODE *logDecode);
|
||||
void libosLogCreateEx(LIBOS_LOG_DECODE *logDecode, const char *pSourceName);
|
||||
#endif
|
||||
|
||||
void libosLogAddLogEx(LIBOS_LOG_DECODE *logDecode, void *buffer, NvU64 bufferSize, NvU32 gpuInstance, NvU32 gpuArch, NvU32 gpuImpl, const char *name);
|
||||
void libosLogAddLog(LIBOS_LOG_DECODE *logDecode, void *buffer, NvU64 bufferSize, NvU32 gpuInstance, const char *name);
|
||||
|
||||
#if LIBOS_LOG_DECODE_ENABLE
|
||||
void libosLogInit(LIBOS_LOG_DECODE *logDecode, elf64_header *elf);
|
||||
void libosLogInitEx(
|
||||
LIBOS_LOG_DECODE *logDecode, elf64_header *elf, NvBool bSynchronousBuffer, NvBool bPtrSymbolResolve);
|
||||
#else
|
||||
void libosLogInit(LIBOS_LOG_DECODE *logDecode, void *elf);
|
||||
void libosLogInitEx(
|
||||
LIBOS_LOG_DECODE *logDecode, void *elf, NvBool bSynchronousBuffer, NvBool bPtrSymbolResolve);
|
||||
#endif // LIBOS_LOG_DECODE_ENABLE
|
||||
|
||||
void libosLogDestroy(LIBOS_LOG_DECODE *logDecode);
|
||||
|
||||
void libosExtractLogs(LIBOS_LOG_DECODE *logDecode, NvBool bSyncNvLog);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // LOGDECODE_H_
|
||||
154
src/common/uproc/os/libos-v2.0.0/include/gsp_fw_wpr_meta.h
Normal file
154
src/common/uproc/os/libos-v2.0.0/include/gsp_fw_wpr_meta.h
Normal file
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2021-2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
// TODO: This file is is not libos specific, so it really does not belong under
|
||||
// uproc/os/libos-v2.0.0. It is used by booter, bootloader, libos, GSP-RM,
|
||||
// and kernel RM. An appropriate location might be uproc/common/inc, but
|
||||
// that directory is not currently synced by DVS for driver builds.
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef GSP_FW_WPR_META_H_
|
||||
#define GSP_FW_WPR_META_H_
|
||||
|
||||
/*!
|
||||
* GSP firmware WPR metadata
|
||||
*
|
||||
* Initialized by CPU-RM and DMA'd to FB, at the end of what will be WPR2.
|
||||
* Verified, and locked in WPR2 by Booter.
|
||||
*
|
||||
* Firmware scrubs the last 256mb of FB, no memory outside of this region
|
||||
* may be used until the FW RM has scrubbed the remainder of memory.
|
||||
*
|
||||
* ---------------------------- <- fbSize (end of FB, 1M aligned)
|
||||
* | VGA WORKSPACE |
|
||||
* ---------------------------- <- vbiosReservedOffset (64K? aligned)
|
||||
* | (potential align. gap) |
|
||||
* ---------------------------- <- gspFwWprEnd (128K aligned)
|
||||
* | FRTS data | (frtsSize is 0 on GA100)
|
||||
* | ------------------------ | <- frtsOffset
|
||||
* | BOOT BIN (e.g. SK + BL) |
|
||||
* ---------------------------- <- bootBinOffset
|
||||
* | GSP FW ELF |
|
||||
* ---------------------------- <- gspFwOffset
|
||||
* | GSP FW (WPR) HEAP |
|
||||
* ---------------------------- <- gspFwHeapOffset
|
||||
* | Booter-placed metadata |
|
||||
* | (struct GspFwWprMeta) |
|
||||
* ---------------------------- <- gspFwWprStart (128K aligned)
|
||||
* | GSP FW (non-WPR) HEAP |
|
||||
* ---------------------------- <- nonWprHeapOffset, gspFwRsvdStart
|
||||
* (GSP_CARVEOUT_SIZE bytes from end of FB)
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
// Magic
|
||||
// BL to use for verification (i.e. Booter locked it in WPR2)
|
||||
NvU64 magic; // = 0xdc3aae21371a60b3;
|
||||
|
||||
// Revision number of Booter-BL-Sequencer handoff interface
|
||||
// Bumped up when we change this interface so it is not backward compatible.
|
||||
// Bumped up when we revoke GSP-RM ucode
|
||||
NvU64 revision; // = 1;
|
||||
|
||||
// ---- Members regarding data in SYSMEM ----------------------------
|
||||
// Consumed by Booter for DMA
|
||||
|
||||
NvU64 sysmemAddrOfRadix3Elf;
|
||||
NvU64 sizeOfRadix3Elf;
|
||||
|
||||
NvU64 sysmemAddrOfBootloader;
|
||||
NvU64 sizeOfBootloader;
|
||||
|
||||
// Offsets inside bootloader image needed by Booter
|
||||
NvU64 bootloaderCodeOffset;
|
||||
NvU64 bootloaderDataOffset;
|
||||
NvU64 bootloaderManifestOffset;
|
||||
|
||||
NvU64 sysmemAddrOfSignature;
|
||||
NvU64 sizeOfSignature;
|
||||
|
||||
// ---- Members describing FB layout --------------------------------
|
||||
NvU64 gspFwRsvdStart;
|
||||
|
||||
NvU64 nonWprHeapOffset;
|
||||
NvU64 nonWprHeapSize;
|
||||
|
||||
NvU64 gspFwWprStart;
|
||||
|
||||
// GSP-RM to use to setup heap.
|
||||
NvU64 gspFwHeapOffset;
|
||||
NvU64 gspFwHeapSize;
|
||||
|
||||
// BL to use to find ELF for jump
|
||||
NvU64 gspFwOffset;
|
||||
// Size is sizeOfRadix3Elf above.
|
||||
|
||||
NvU64 bootBinOffset;
|
||||
// Size is sizeOfBootloader above.
|
||||
|
||||
NvU64 frtsOffset;
|
||||
NvU64 frtsSize;
|
||||
|
||||
NvU64 gspFwWprEnd;
|
||||
|
||||
// GSP-RM to use for fbRegionInfo?
|
||||
NvU64 fbSize;
|
||||
|
||||
// ---- Other members -----------------------------------------------
|
||||
|
||||
// GSP-RM to use for fbRegionInfo?
|
||||
NvU64 vgaWorkspaceOffset;
|
||||
NvU64 vgaWorkspaceSize;
|
||||
|
||||
// Boot count. Used to determine whether to load the firmware image.
|
||||
NvU64 bootCount;
|
||||
|
||||
// TODO: the partitionRpc* fields below do not really belong in this
|
||||
// structure. The values are patched in by the partition bootstrapper
|
||||
// when GSP-RM is booted in a partition, and this structure was a
|
||||
// convenient place for the bootstrapper to access them. These should
|
||||
// be moved to a different comm. mechanism between the bootstrapper
|
||||
// and the GSP-RM tasks.
|
||||
|
||||
// Shared partition RPC memory (physical address)
|
||||
NvU64 partitionRpcAddr;
|
||||
|
||||
// Offsets relative to partitionRpcAddr
|
||||
NvU16 partitionRpcRequestOffset;
|
||||
NvU16 partitionRpcReplyOffset;
|
||||
|
||||
// Pad structure to exactly 256 bytes. Can replace padding with additional
|
||||
// fields without incrementing revision. Padding initialized to 0.
|
||||
NvU32 padding[7];
|
||||
|
||||
// BL to use for verification (i.e. Booter says OK to boot)
|
||||
NvU64 verified; // 0x0 -> unverified, 0xa0a0a0a0a0a0a0a0 -> verified
|
||||
|
||||
} GspFwWprMeta;
|
||||
|
||||
#define GSP_FW_WPR_META_VERIFIED 0xa0a0a0a0a0a0a0a0ULL
|
||||
#define GSP_FW_WPR_META_REVISION 1
|
||||
#define GSP_FW_WPR_META_MAGIC 0xdc3aae21371a60b3ULL
|
||||
|
||||
#endif // GSP_FW_WPR_META_H_
|
||||
58
src/common/uproc/os/libos-v2.0.0/include/libos_init_args.h
Normal file
58
src/common/uproc/os/libos-v2.0.0/include/libos_init_args.h
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2018-2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// @todo: Remove this once chips_a/drivers/resman/arch/nvalloc/common/inc/riscvifriscv.h has been
|
||||
// switched to directly include this file.
|
||||
#if !defined(RISCVIFRISCV_H) && !defined(LIBOS_INIT_H_)
|
||||
#define LIBOS_INIT_H_
|
||||
|
||||
#define LIBOS_MEMORY_REGION_INIT_ARGUMENTS_MAX 4096
|
||||
|
||||
typedef NvU64 LibosAddress;
|
||||
|
||||
typedef enum {
|
||||
LIBOS_MEMORY_REGION_NONE,
|
||||
LIBOS_MEMORY_REGION_CONTIGUOUS,
|
||||
LIBOS_MEMORY_REGION_RADIX3
|
||||
} LibosMemoryRegionKind;
|
||||
|
||||
typedef enum {
|
||||
LIBOS_MEMORY_REGION_LOC_NONE,
|
||||
LIBOS_MEMORY_REGION_LOC_SYSMEM,
|
||||
LIBOS_MEMORY_REGION_LOC_FB
|
||||
} LibosMemoryRegionLoc;
|
||||
|
||||
#define LIBOS_MEMORY_REGION_RADIX_PAGE_SIZE 4096
|
||||
#define LIBOS_MEMORY_REGION_RADIX_PAGE_LOG2 12
|
||||
typedef struct
|
||||
{
|
||||
LibosAddress id8; // Id tag.
|
||||
LibosAddress pa; // Physical address.
|
||||
LibosAddress size; // Size of memory area.
|
||||
NvU8 kind; // See LibosMemoryRegionKind above.
|
||||
NvU8 loc; // See LibosMemoryRegionLoc above.
|
||||
} LibosMemoryRegionInitArgument;
|
||||
|
||||
#endif
|
||||
195
src/common/uproc/os/libos-v2.0.0/include/libos_log.h
Normal file
195
src/common/uproc/os/libos-v2.0.0/include/libos_log.h
Normal file
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: Copyright (c) 2018-2020 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
|
||||
* SPDX-License-Identifier: MIT
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef LIBOS_LOGGER_H_
|
||||
#define LIBOS_LOGGER_H_
|
||||
|
||||
#include "nvtypes.h"
|
||||
|
||||
/**
|
||||
* @brief The log metadata structures and format strings are stripped
|
||||
* These structures are emitted into the .logging section
|
||||
* which is stripped from the image as the final build step.
|
||||
*
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
NV_DECLARE_ALIGNED(const char *filename, 8);
|
||||
NV_DECLARE_ALIGNED(const char *format, 8);
|
||||
NV_DECLARE_ALIGNED(NvU32 lineNumber, 8);
|
||||
NvU8 argumentCount; //! Count of arguments not including format string.
|
||||
NvU8 printLevel;
|
||||
} libosLogMetadata;
|
||||
|
||||
/*!
|
||||
* Count arguments
|
||||
*
|
||||
*/
|
||||
#define LIBOS_MACRO_GET_COUNT(...) \
|
||||
LIBOS_MACRO_GET_19TH(__VA_ARGS__, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
|
||||
#define LIBOS_MACRO_GET_19TH( \
|
||||
_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, N, ...) \
|
||||
N
|
||||
|
||||
/*!
|
||||
* Utility
|
||||
*
|
||||
*/
|
||||
#define LIBOS_MACRO_PASTE(fmt, b) fmt##b
|
||||
#define LIBOS_MACRO_PASTE_EVAL(fmt, b) LIBOS_MACRO_PASTE(fmt, b)
|
||||
#define LIBOS_MACRO_FIRST(format_string, ...) format_string
|
||||
|
||||
/*!
|
||||
* Cast remaining log arguments to integers for storage
|
||||
*
|
||||
*/
|
||||
#define LIBOS_LOG_BUILD_ARG(a) (NvU64)(a),
|
||||
#define LIBOS_LOG_BUILD_1(fmt)
|
||||
#define LIBOS_LOG_BUILD_2(fmt, b) LIBOS_LOG_BUILD_ARG(b)
|
||||
#define LIBOS_LOG_BUILD_3(fmt, b, c) LIBOS_LOG_BUILD_ARG(b) LIBOS_LOG_BUILD_ARG(c)
|
||||
#define LIBOS_LOG_BUILD_4(fmt, b, c, d) LIBOS_LOG_BUILD_ARG(b) LIBOS_LOG_BUILD_ARG(c) LIBOS_LOG_BUILD_ARG(d)
|
||||
#define LIBOS_LOG_BUILD_5(fmt, b, c, d, e) \
|
||||
LIBOS_LOG_BUILD_ARG(b) LIBOS_LOG_BUILD_ARG(c) LIBOS_LOG_BUILD_ARG(d) LIBOS_LOG_BUILD_ARG(e)
|
||||
#define LIBOS_LOG_BUILD_6(fmt, b, c, d, e, f) \
|
||||
LIBOS_LOG_BUILD_ARG(b) \
|
||||
LIBOS_LOG_BUILD_ARG(c) LIBOS_LOG_BUILD_ARG(d) LIBOS_LOG_BUILD_ARG(e) LIBOS_LOG_BUILD_ARG(f)
|
||||
#define LIBOS_LOG_BUILD_7(fmt, b, c, d, e, f, g) \
|
||||
LIBOS_LOG_BUILD_ARG(b) \
|
||||
LIBOS_LOG_BUILD_ARG(c) LIBOS_LOG_BUILD_ARG(d) LIBOS_LOG_BUILD_ARG(e) LIBOS_LOG_BUILD_ARG(f) \
|
||||
LIBOS_LOG_BUILD_ARG(g)
|
||||
#define LIBOS_LOG_BUILD_8(fmt, b, c, d, e, f, g, h) \
|
||||
LIBOS_LOG_BUILD_ARG(b) \
|
||||
LIBOS_LOG_BUILD_ARG(c) LIBOS_LOG_BUILD_ARG(d) LIBOS_LOG_BUILD_ARG(e) LIBOS_LOG_BUILD_ARG(f) \
|
||||
LIBOS_LOG_BUILD_ARG(g) LIBOS_LOG_BUILD_ARG(h)
|
||||
#define LIBOS_LOG_BUILD_9(fmt, b, c, d, e, f, g, h, i) \
|
||||
LIBOS_LOG_BUILD_ARG(b) \
|
||||
LIBOS_LOG_BUILD_ARG(c) LIBOS_LOG_BUILD_ARG(d) LIBOS_LOG_BUILD_ARG(e) LIBOS_LOG_BUILD_ARG(f) \
|
||||
LIBOS_LOG_BUILD_ARG(g) LIBOS_LOG_BUILD_ARG(h) LIBOS_LOG_BUILD_ARG(i)
|
||||
#define LIBOS_LOG_BUILD_10(fmt, b, c, d, e, f, g, h, i, j) \
|
||||
LIBOS_LOG_BUILD_ARG(b) \
|
||||
LIBOS_LOG_BUILD_ARG(c) LIBOS_LOG_BUILD_ARG(d) LIBOS_LOG_BUILD_ARG(e) LIBOS_LOG_BUILD_ARG(f) \
|
||||
LIBOS_LOG_BUILD_ARG(g) LIBOS_LOG_BUILD_ARG(h) LIBOS_LOG_BUILD_ARG(i) LIBOS_LOG_BUILD_ARG(j)
|
||||
#define LIBOS_LOG_BUILD_11(fmt, b, c, d, e, f, g, h, i, j, k) \
|
||||
LIBOS_LOG_BUILD_ARG(b) \
|
||||
LIBOS_LOG_BUILD_ARG(c) LIBOS_LOG_BUILD_ARG(d) LIBOS_LOG_BUILD_ARG(e) LIBOS_LOG_BUILD_ARG(f) \
|
||||
LIBOS_LOG_BUILD_ARG(g) LIBOS_LOG_BUILD_ARG(h) LIBOS_LOG_BUILD_ARG(i) LIBOS_LOG_BUILD_ARG(j) \
|
||||
LIBOS_LOG_BUILD_ARG(k)
|
||||
#define LIBOS_LOG_BUILD_12(fmt, b, c, d, e, f, g, h, i, j, k, l) \
|
||||
LIBOS_LOG_BUILD_ARG(b) \
|
||||
LIBOS_LOG_BUILD_ARG(c) LIBOS_LOG_BUILD_ARG(d) LIBOS_LOG_BUILD_ARG(e) LIBOS_LOG_BUILD_ARG(f) \
|
||||
LIBOS_LOG_BUILD_ARG(g) LIBOS_LOG_BUILD_ARG(h) LIBOS_LOG_BUILD_ARG(i) LIBOS_LOG_BUILD_ARG(j) \
|
||||
LIBOS_LOG_BUILD_ARG(k) LIBOS_LOG_BUILD_ARG(l)
|
||||
#define LIBOS_LOG_BUILD_13(fmt, b, c, d, e, f, g, h, i, j, k, l, m) \
|
||||
LIBOS_LOG_BUILD_ARG(b) \
|
||||
LIBOS_LOG_BUILD_ARG(c) LIBOS_LOG_BUILD_ARG(d) LIBOS_LOG_BUILD_ARG(e) LIBOS_LOG_BUILD_ARG(f) \
|
||||
LIBOS_LOG_BUILD_ARG(g) LIBOS_LOG_BUILD_ARG(h) LIBOS_LOG_BUILD_ARG(i) LIBOS_LOG_BUILD_ARG(j) \
|
||||
LIBOS_LOG_BUILD_ARG(k) LIBOS_LOG_BUILD_ARG(l) LIBOS_LOG_BUILD_ARG(m)
|
||||
#define LIBOS_LOG_BUILD_14(fmt, b, c, d, e, f, g, h, i, j, k, l, m, n) \
|
||||
LIBOS_LOG_BUILD_ARG(b) \
|
||||
LIBOS_LOG_BUILD_ARG(c) LIBOS_LOG_BUILD_ARG(d) LIBOS_LOG_BUILD_ARG(e) LIBOS_LOG_BUILD_ARG(f) \
|
||||
LIBOS_LOG_BUILD_ARG(g) LIBOS_LOG_BUILD_ARG(h) LIBOS_LOG_BUILD_ARG(i) LIBOS_LOG_BUILD_ARG(j) \
|
||||
LIBOS_LOG_BUILD_ARG(k) LIBOS_LOG_BUILD_ARG(l) LIBOS_LOG_BUILD_ARG(m) LIBOS_LOG_BUILD_ARG(n)
|
||||
#define LIBOS_LOG_BUILD_15(fmt, b, c, d, e, f, g, h, i, j, k, l, m, n, o) \
|
||||
LIBOS_LOG_BUILD_ARG(b) \
|
||||
LIBOS_LOG_BUILD_ARG(c) LIBOS_LOG_BUILD_ARG(d) LIBOS_LOG_BUILD_ARG(e) LIBOS_LOG_BUILD_ARG(f) \
|
||||
LIBOS_LOG_BUILD_ARG(g) LIBOS_LOG_BUILD_ARG(h) LIBOS_LOG_BUILD_ARG(i) LIBOS_LOG_BUILD_ARG(j) \
|
||||
LIBOS_LOG_BUILD_ARG(k) LIBOS_LOG_BUILD_ARG(l) LIBOS_LOG_BUILD_ARG(m) LIBOS_LOG_BUILD_ARG(n) \
|
||||
LIBOS_LOG_BUILD_ARG(o)
|
||||
#define LIBOS_LOG_BUILD_16(fmt, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) \
|
||||
LIBOS_LOG_BUILD_ARG(b) \
|
||||
LIBOS_LOG_BUILD_ARG(c) LIBOS_LOG_BUILD_ARG(d) LIBOS_LOG_BUILD_ARG(e) LIBOS_LOG_BUILD_ARG(f) \
|
||||
LIBOS_LOG_BUILD_ARG(g) LIBOS_LOG_BUILD_ARG(h) LIBOS_LOG_BUILD_ARG(i) LIBOS_LOG_BUILD_ARG(j) \
|
||||
LIBOS_LOG_BUILD_ARG(k) LIBOS_LOG_BUILD_ARG(l) LIBOS_LOG_BUILD_ARG(m) LIBOS_LOG_BUILD_ARG(n) \
|
||||
LIBOS_LOG_BUILD_ARG(o) LIBOS_LOG_BUILD_ARG(p)
|
||||
#define LIBOS_LOG_BUILD_17(fmt, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q) \
|
||||
LIBOS_LOG_BUILD_ARG(b) \
|
||||
LIBOS_LOG_BUILD_ARG(c) LIBOS_LOG_BUILD_ARG(d) LIBOS_LOG_BUILD_ARG(e) LIBOS_LOG_BUILD_ARG(f) \
|
||||
LIBOS_LOG_BUILD_ARG(g) LIBOS_LOG_BUILD_ARG(h) LIBOS_LOG_BUILD_ARG(i) LIBOS_LOG_BUILD_ARG(j) \
|
||||
LIBOS_LOG_BUILD_ARG(k) LIBOS_LOG_BUILD_ARG(l) LIBOS_LOG_BUILD_ARG(m) LIBOS_LOG_BUILD_ARG(n) \
|
||||
LIBOS_LOG_BUILD_ARG(o) LIBOS_LOG_BUILD_ARG(p) LIBOS_LOG_BUILD_ARG(q)
|
||||
#define LIBOS_LOG_BUILD_18(fmt, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r) \
|
||||
LIBOS_LOG_BUILD_ARG(b) \
|
||||
LIBOS_LOG_BUILD_ARG(c) LIBOS_LOG_BUILD_ARG(d) LIBOS_LOG_BUILD_ARG(e) LIBOS_LOG_BUILD_ARG(f) \
|
||||
LIBOS_LOG_BUILD_ARG(g) LIBOS_LOG_BUILD_ARG(h) LIBOS_LOG_BUILD_ARG(i) LIBOS_LOG_BUILD_ARG(j) \
|
||||
LIBOS_LOG_BUILD_ARG(k) LIBOS_LOG_BUILD_ARG(l) LIBOS_LOG_BUILD_ARG(m) LIBOS_LOG_BUILD_ARG(n) \
|
||||
LIBOS_LOG_BUILD_ARG(o) LIBOS_LOG_BUILD_ARG(p) LIBOS_LOG_BUILD_ARG(q) LIBOS_LOG_BUILD_ARG(r)
|
||||
|
||||
#define LIBOS_LOG_BUILD_APPLY(F, ...) F(__VA_ARGS__)
|
||||
#define APPLY_REMAINDER(...) \
|
||||
LIBOS_LOG_BUILD_APPLY( \
|
||||
LIBOS_MACRO_PASTE_EVAL(LIBOS_LOG_BUILD_, LIBOS_MACRO_GET_COUNT(__VA_ARGS__)), __VA_ARGS__)
|
||||
|
||||
#define LOG_LEVEL_INFO 0
|
||||
#define LOG_LEVEL_ERROR 1
|
||||
|
||||
# define LIBOS_SECTION_LOGGING __attribute__((section(".logging")))
|
||||
|
||||
#ifdef LIBOS_LOGGING_METADATA_SPLIT
|
||||
/*!
|
||||
* When the METADATA_SPLIT feature is enabled, libos print data is split between 4 input sections (all of which
|
||||
* must be dropped from the final image). The default .logging is used for str literals and custom strings which
|
||||
* are directly referenced by pointer (for %s substitution); .logging_const is used for format strings and the
|
||||
* aux metadata; and .logging_metadata is used for metadata vars.
|
||||
*
|
||||
* The idea is to have a split where metadata-only changes (i.e. changing what data gets printed, line number changes
|
||||
* in file with prints, file renames) will usually not affect the main image, and can be bundled together and
|
||||
* relied upon to trigger custom ucode build release behavior.
|
||||
* The only exception is renaming headers with prints inside static inline functions; since these don't overlap
|
||||
* with basenames, and we can't reliably get a nonvolatile version of a header file name here, such name changes
|
||||
* alone won't be able to trigger ucode releases.
|
||||
*/
|
||||
# define LIBOS_SECTION_LOGGING_CONST __attribute__((section(".logging_const")))
|
||||
# define LIBOS_SECTION_LOGGING_METADATA __attribute__((section(".logging_metadata")))
|
||||
# define LIBOS_LOGGING_AUX_METADATA_DUMP \
|
||||
static const LIBOS_SECTION_LOGGING_CONST int libos_dummy_line[] LIBOS_ATTR_USED = {__LINE__};
|
||||
#else // LIBOS_LOGGING_VOLATILE_METADATA_SPLIT
|
||||
# define LIBOS_SECTION_LOGGING_CONST LIBOS_SECTION_LOGGING
|
||||
# define LIBOS_SECTION_LOGGING_METADATA LIBOS_SECTION_LOGGING
|
||||
# define LIBOS_LOGGING_AUX_METADATA_DUMP
|
||||
#endif // LIBOS_LOGGING_VOLATILE_METADATA_SPLIT
|
||||
|
||||
/*!
|
||||
* Used for log variables which we want to dump; clients may want to pick these up to check for metadata changes
|
||||
*/
|
||||
#define LIBOS_ATTR_USED __attribute__((used))
|
||||
|
||||
/*!
|
||||
* Cast remaining log arguments to integers for storage
|
||||
*/
|
||||
#define LIBOS_LOG_INTERNAL(dispatcher, level, ...) \
|
||||
do \
|
||||
{ \
|
||||
static const LIBOS_SECTION_LOGGING_CONST char libos_pvt_format[] = {LIBOS_MACRO_FIRST(__VA_ARGS__)}; \
|
||||
static const LIBOS_SECTION_LOGGING_CONST char libos_pvt_file[] = {__FILE__}; \
|
||||
LIBOS_LOGGING_AUX_METADATA_DUMP; \
|
||||
static const LIBOS_SECTION_LOGGING_METADATA libosLogMetadata libos_pvt_meta = { \
|
||||
.filename = &libos_pvt_file[0], \
|
||||
.format = &libos_pvt_format[0], \
|
||||
.lineNumber = __LINE__, \
|
||||
.argumentCount = LIBOS_MACRO_GET_COUNT(__VA_ARGS__) - 1, \
|
||||
.printLevel = level}; \
|
||||
const NvU64 tokens[] = {APPLY_REMAINDER(__VA_ARGS__)(NvU64) & libos_pvt_meta}; \
|
||||
dispatcher(sizeof(tokens) / sizeof(*tokens), &tokens[0]); \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user