File: LlamaRuntimeLinker.cpp

package info (click to toggle)
firefox 144.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 4,637,504 kB
  • sloc: cpp: 7,576,692; javascript: 6,430,831; ansic: 3,748,119; python: 1,398,978; xml: 628,810; asm: 438,679; java: 186,194; sh: 63,212; makefile: 19,159; objc: 13,086; perl: 12,986; yacc: 4,583; cs: 3,846; pascal: 3,448; lex: 1,720; ruby: 1,003; exp: 762; php: 436; lisp: 258; awk: 247; sql: 66; sed: 53; csh: 10
file content (170 lines) | stat: -rw-r--r-- 5,074 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

#include "LlamaRuntimeLinker.h"

#include "mozilla/FileUtils.h"
#include "mozilla/Logging.h"
#include "nsLocalFile.h"
#include "nsXPCOMPrivate.h"
#include "prlink.h"

mozilla::LazyLogModule gLlamaLinkerLog("LlamaRuntimeLinker");

#define LOG(level, fmt, ...) \
  MOZ_LOG(gLlamaLinkerLog, level, ("[LlamaRuntimeLinker] " fmt, ##__VA_ARGS__))

namespace mozilla::llama {

LlamaLibWrapper LlamaRuntimeLinker::sLlamaLib;
LlamaRuntimeLinker::LinkStatus LlamaRuntimeLinker::sLinkStatus =
    LinkStatus_INIT;

static PRLibrary* LoadLlamaLib(nsIFile* aFile) {
  PRLibSpec lspec;
  PathString path = aFile->NativePath();
#ifdef XP_WIN
  lspec.type = PR_LibSpec_PathnameU;
  lspec.value.pathname_u = path.get();
#else
#  if defined(XP_OPENBSD)
  /* on OpenBSD, libraries are preloaded before sandboxing so make sure only
   * the filename is passed to PR_LoadLibraryWithFlags(), dlopen() will return
   * the preloaded library handle instead of failing to find it due to
   * sandboxing */
  nsAutoCString leaf;
  nsresult rv = aFile->GetNativeLeafName(leaf);
  if (NS_SUCCEEDED(rv)) {
    path = PathString(leaf);
  }
#  endif  // defined(XP_OPENBSD)
  lspec.type = PR_LibSpec_Pathname;
  lspec.value.pathname = path.get();
#endif
#ifdef MOZ_WIDGET_ANDROID
  PRLibrary* lib = PR_LoadLibraryWithFlags(lspec, PR_LD_NOW | PR_LD_GLOBAL);
#else
  PRLibrary* lib = PR_LoadLibraryWithFlags(lspec, PR_LD_NOW | PR_LD_LOCAL);
#endif
  if (!lib) {
    LOG(LogLevel::Error, "unable to load library %s",
        aFile->HumanReadablePath().get());
  }
  return lib;
}

LlamaLibWrapper::LinkResult LlamaLibWrapper::Link() {
  if (!mLlamaLib) {
    Unlink();
    return LinkResult::NoProvidedLib;
  }

  LOG(LogLevel::Debug, "Linking llama library symbols");

  // Use X-macros to bind all functions
#define BIND_FUNCTION(ret, name, params)                             \
  if (!((name) = (decltype(name))PR_FindSymbol(mLlamaLib, #name))) { \
    LOG(LogLevel::Error, "Couldn't load function " #name);           \
    Unlink();                                                        \
    return LinkResult::MissingFunction;                              \
  }

  MOZINFERENCE_FUNCTION_LIST(BIND_FUNCTION)

#undef BIND_FUNCTION

  LOG(LogLevel::Debug, "Successfully linked all llama functions");
  return LinkResult::Success;
}

void LlamaLibWrapper::Unlink() {
  if (mLlamaLib) {
    PR_UnloadLibrary(mLlamaLib);
    mLlamaLib = nullptr;
  }

  // Clear all function pointers using X-macros
#define CLEAR_FUNCTION(ret, name, params) name = nullptr;
  MOZINFERENCE_FUNCTION_LIST(CLEAR_FUNCTION)
#undef CLEAR_FUNCTION
}

/* static */
bool LlamaRuntimeLinker::Init() {
  // Quick return if already initialized
  if (sLinkStatus == LinkStatus_SUCCEEDED) {
    return true;
  }
  if (sLinkStatus == LinkStatus_FAILED) {
    return false;
  }

  LOG(LogLevel::Debug, "Initializing llama runtime linker");

  sLinkStatus = LinkStatus_FAILED;

  // Get the path to the current executable/library
#ifdef XP_WIN
  PathString path =
      GetLibraryFilePathname(LXUL_DLL, (PRFuncPtr)&LlamaRuntimeLinker::Init);
#else
  PathString path =
      GetLibraryFilePathname(XUL_DLL, (PRFuncPtr)&LlamaRuntimeLinker::Init);
#endif
  if (path.IsEmpty()) {
    LOG(LogLevel::Error, "Failed to get library path");
    return false;
  }

  nsCOMPtr<nsIFile> libFile;
  if (NS_FAILED(NS_NewPathStringLocalFile(path, getter_AddRefs(libFile)))) {
    LOG(LogLevel::Error, "Failed to create file object from path");
    return false;
  }

  // Handle test environments
  if (getenv("MOZ_RUN_GTEST")
#ifdef FUZZING
      || getenv("FUZZER")
#endif
  ) {
    // In test environments, the library is in the parent directory
    nsCOMPtr<nsIFile> parent;
    if (NS_FAILED(libFile->GetParent(getter_AddRefs(parent)))) {
      LOG(LogLevel::Error, "Failed to get parent directory");
      return false;
    }
    libFile = parent;
  }

  // Set the library name with proper prefix and suffix
  if (NS_FAILED(libFile->SetNativeLeafName(
          MOZ_DLL_PREFIX "mozinference" MOZ_DLL_SUFFIX ""_ns))) {
    LOG(LogLevel::Error, "Failed to set library name");
    return false;
  }

  LOG(LogLevel::Debug, "Attempting to load library from: %s",
      libFile->HumanReadablePath().get());

  sLlamaLib.mLlamaLib = LoadLlamaLib(libFile);
  if (!sLlamaLib.mLlamaLib) {
    LOG(LogLevel::Error, "Failed to load llama library");
    return false;
  }

  LlamaLibWrapper::LinkResult res = sLlamaLib.Link();
  if (res != LlamaLibWrapper::LinkResult::Success) {
    LOG(LogLevel::Error, "Failed to link llama library: %d", (int)res);
    return false;
  }

  sLinkStatus = LinkStatus_SUCCEEDED;
  LOG(LogLevel::Info, "Successfully initialized llama runtime linker");
  return true;
}

}  // namespace mozilla::llama