blob: f5046173789add784387ef0510a85047fd0707e2 [file] [log] [blame]
// Copyright 2023 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef LIB_LD_STARTUP_DIAGNOSTICS_H_
#define LIB_LD_STARTUP_DIAGNOSTICS_H_
#include <lib/ld/diagnostics.h>
#include <cassert>
#include <cstdarg>
#include <string_view>
#include <type_traits>
#include <utility>
namespace ld {
// This is declared in the OS-specific header (posix.h or zircon.h).
struct StartupData;
// This is the version of the elfldltl::DiagnosticsFlags API always used in the
// startup dynamic linker: allow warnings; keep going after errors. Before
// beginning relocation and before handing off control, the diagnostics
// object's error count will be checked to bail out safely after doing as much
// work as possible to report all the detailed errors that can be found.
struct StartupDiagnosticsFlags {
[[no_unique_address]] elfldltl::FixedBool<true, 0> multiple_errors;
[[no_unique_address]] elfldltl::FixedBool<false, 1> warnings_are_errors;
[[no_unique_address]] elfldltl::FixedBool<false, 2> extra_checking;
};
// This provides the Report callable object for Diagnostics. It uses the
// printf engine to ultimately call StartupMessage with the captured
// StartupData reference.
class DiagnosticsReport : public ModuleDiagnosticsPrintfReportBase<DiagnosticsReport> {
public:
constexpr explicit DiagnosticsReport(StartupData& startup) : startup_(startup) {}
// ModuleDiagnosticsPrintfReportBase calls this like it's printf.
void Printf(const char* format, ...) const;
// StartupModule is a typedef in the OS-specific header, so each one defines
// the one explicit specialization that will be used. This can't just use a
// simple non-template forward declaration (as with StartupData) because
// StartupModule is a typedef and not a class or struct.
template <class StartupModule>
void ReportModuleLoaded(const StartupModule& module) const;
private:
void Printf(const char* format, va_list args) const;
StartupData& startup_;
std::string_view module_;
};
// This is the main Diagnostics object for the startup dynamic linker. It
// holds only the current-module state, so it can be constructed ephemerally.
struct Diagnostics : elfldltl::Diagnostics<DiagnosticsReport, StartupDiagnosticsFlags> {
using Base = elfldltl::Diagnostics<DiagnosticsReport, StartupDiagnosticsFlags>;
constexpr explicit Diagnostics(StartupData& startup) : Base{DiagnosticsReport{startup}} {}
};
// This is called before proceeding from loading to relocation / linking, and
// then again when proceeding from final cleanup to transferring control.
void CheckErrors(Diagnostics& diag);
} // namespace ld
#endif // LIB_LD_STARTUP_DIAGNOSTICS_H_