1*84e33947SAndroid Build Coastguard Worker /*
2*84e33947SAndroid Build Coastguard Worker * Copyright (C) 2020 The Android Open Source Project
3*84e33947SAndroid Build Coastguard Worker *
4*84e33947SAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*84e33947SAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*84e33947SAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*84e33947SAndroid Build Coastguard Worker *
8*84e33947SAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*84e33947SAndroid Build Coastguard Worker *
10*84e33947SAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*84e33947SAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*84e33947SAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*84e33947SAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*84e33947SAndroid Build Coastguard Worker * limitations under the License.
15*84e33947SAndroid Build Coastguard Worker */
16*84e33947SAndroid Build Coastguard Worker
17*84e33947SAndroid Build Coastguard Worker #include <dlfcn.h>
18*84e33947SAndroid Build Coastguard Worker #include <cctype>
19*84e33947SAndroid Build Coastguard Worker #include <cmath>
20*84e33947SAndroid Build Coastguard Worker #include <cstring>
21*84e33947SAndroid Build Coastguard Worker
22*84e33947SAndroid Build Coastguard Worker #include "chre/platform/shared/nanoapp_loader.h"
23*84e33947SAndroid Build Coastguard Worker
24*84e33947SAndroid Build Coastguard Worker #include "chre.h"
25*84e33947SAndroid Build Coastguard Worker #include "chre/platform/assert.h"
26*84e33947SAndroid Build Coastguard Worker #include "chre/platform/fatal_error.h"
27*84e33947SAndroid Build Coastguard Worker #include "chre/platform/shared/debug_dump.h"
28*84e33947SAndroid Build Coastguard Worker #include "chre/platform/shared/memory.h"
29*84e33947SAndroid Build Coastguard Worker #include "chre/platform/shared/nanoapp/tokenized_log.h"
30*84e33947SAndroid Build Coastguard Worker #include "chre/platform/shared/platform_cache_management.h"
31*84e33947SAndroid Build Coastguard Worker #include "chre/util/dynamic_vector.h"
32*84e33947SAndroid Build Coastguard Worker #include "chre/util/macros.h"
33*84e33947SAndroid Build Coastguard Worker
34*84e33947SAndroid Build Coastguard Worker #ifdef CHREX_SYMBOL_EXTENSIONS
35*84e33947SAndroid Build Coastguard Worker #include "chre/extensions/platform/symbol_list.h"
36*84e33947SAndroid Build Coastguard Worker #endif
37*84e33947SAndroid Build Coastguard Worker
38*84e33947SAndroid Build Coastguard Worker #ifndef CHRE_LOADER_ARCH
39*84e33947SAndroid Build Coastguard Worker #define CHRE_LOADER_ARCH EM_ARM
40*84e33947SAndroid Build Coastguard Worker #endif // CHRE_LOADER_ARCH
41*84e33947SAndroid Build Coastguard Worker
42*84e33947SAndroid Build Coastguard Worker namespace chre {
43*84e33947SAndroid Build Coastguard Worker namespace {
44*84e33947SAndroid Build Coastguard Worker
45*84e33947SAndroid Build Coastguard Worker using ElfHeader = ElfW(Ehdr);
46*84e33947SAndroid Build Coastguard Worker using ProgramHeader = ElfW(Phdr);
47*84e33947SAndroid Build Coastguard Worker
48*84e33947SAndroid Build Coastguard Worker struct ExportedData {
49*84e33947SAndroid Build Coastguard Worker void *data;
50*84e33947SAndroid Build Coastguard Worker const char *dataName;
51*84e33947SAndroid Build Coastguard Worker };
52*84e33947SAndroid Build Coastguard Worker
53*84e33947SAndroid Build Coastguard Worker //! If non-null, a nanoapp is currently being loaded. This allows certain C
54*84e33947SAndroid Build Coastguard Worker //! functions to access the nanoapp if called during static init.
55*84e33947SAndroid Build Coastguard Worker NanoappLoader *gCurrentlyLoadingNanoapp = nullptr;
56*84e33947SAndroid Build Coastguard Worker //! Indicates whether a failure occurred during static initialization.
57*84e33947SAndroid Build Coastguard Worker bool gStaticInitFailure = false;
58*84e33947SAndroid Build Coastguard Worker
deleteOpOverride(void *,unsigned int size)59*84e33947SAndroid Build Coastguard Worker void deleteOpOverride(void* /* ptr */, unsigned int size) {
60*84e33947SAndroid Build Coastguard Worker FATAL_ERROR("Nanoapp: delete(void *, unsigned int) override : sz = %u", size);
61*84e33947SAndroid Build Coastguard Worker }
62*84e33947SAndroid Build Coastguard Worker
63*84e33947SAndroid Build Coastguard Worker #ifdef __clang__
deleteOp2Override(void *)64*84e33947SAndroid Build Coastguard Worker void deleteOp2Override(void*) {
65*84e33947SAndroid Build Coastguard Worker FATAL_ERROR("Nanoapp: delete(void *)");
66*84e33947SAndroid Build Coastguard Worker }
67*84e33947SAndroid Build Coastguard Worker #endif
68*84e33947SAndroid Build Coastguard Worker
atexitInternal(struct AtExitCallback & cb)69*84e33947SAndroid Build Coastguard Worker int atexitInternal(struct AtExitCallback &cb) {
70*84e33947SAndroid Build Coastguard Worker if (gCurrentlyLoadingNanoapp == nullptr) {
71*84e33947SAndroid Build Coastguard Worker CHRE_ASSERT_LOG(false,
72*84e33947SAndroid Build Coastguard Worker "atexit is only supported during static initialization.");
73*84e33947SAndroid Build Coastguard Worker return -1;
74*84e33947SAndroid Build Coastguard Worker }
75*84e33947SAndroid Build Coastguard Worker
76*84e33947SAndroid Build Coastguard Worker gCurrentlyLoadingNanoapp->registerAtexitFunction(cb);
77*84e33947SAndroid Build Coastguard Worker return 0;
78*84e33947SAndroid Build Coastguard Worker }
79*84e33947SAndroid Build Coastguard Worker
80*84e33947SAndroid Build Coastguard Worker // atexit is used to register functions that must be called when a binary is
81*84e33947SAndroid Build Coastguard Worker // removed from the system. The call back function has an arg (void *)
cxaAtexitOverride(void (* func)(void *),void * arg,void * dso)82*84e33947SAndroid Build Coastguard Worker int cxaAtexitOverride(void (*func)(void *), void *arg, void *dso) {
83*84e33947SAndroid Build Coastguard Worker LOGV("__cxa_atexit invoked with %p, %p, %p", func, arg, dso);
84*84e33947SAndroid Build Coastguard Worker struct AtExitCallback cb(func, arg);
85*84e33947SAndroid Build Coastguard Worker atexitInternal(cb);
86*84e33947SAndroid Build Coastguard Worker return 0;
87*84e33947SAndroid Build Coastguard Worker }
88*84e33947SAndroid Build Coastguard Worker
89*84e33947SAndroid Build Coastguard Worker // The call back function has no arg.
atexitOverride(void (* func)(void))90*84e33947SAndroid Build Coastguard Worker int atexitOverride(void (*func)(void)) {
91*84e33947SAndroid Build Coastguard Worker LOGV("atexit invoked with %p", func);
92*84e33947SAndroid Build Coastguard Worker struct AtExitCallback cb(func);
93*84e33947SAndroid Build Coastguard Worker atexitInternal(cb);
94*84e33947SAndroid Build Coastguard Worker return 0;
95*84e33947SAndroid Build Coastguard Worker }
96*84e33947SAndroid Build Coastguard Worker
97*84e33947SAndroid Build Coastguard Worker // The following functions from the cmath header need to be overridden, since
98*84e33947SAndroid Build Coastguard Worker // they're overloaded functions, and we need to specify explicit types of the
99*84e33947SAndroid Build Coastguard Worker // template for the compiler.
frexpOverride(double value,int * exp)100*84e33947SAndroid Build Coastguard Worker double frexpOverride(double value, int *exp) {
101*84e33947SAndroid Build Coastguard Worker return frexp(value, exp);
102*84e33947SAndroid Build Coastguard Worker }
103*84e33947SAndroid Build Coastguard Worker
fmaxOverride(double x,double y)104*84e33947SAndroid Build Coastguard Worker double fmaxOverride(double x, double y) {
105*84e33947SAndroid Build Coastguard Worker return fmax(x, y);
106*84e33947SAndroid Build Coastguard Worker }
107*84e33947SAndroid Build Coastguard Worker
fminOverride(double x,double y)108*84e33947SAndroid Build Coastguard Worker double fminOverride(double x, double y) {
109*84e33947SAndroid Build Coastguard Worker return fmin(x, y);
110*84e33947SAndroid Build Coastguard Worker }
111*84e33947SAndroid Build Coastguard Worker
floorOverride(double value)112*84e33947SAndroid Build Coastguard Worker double floorOverride(double value) {
113*84e33947SAndroid Build Coastguard Worker return floor(value);
114*84e33947SAndroid Build Coastguard Worker }
115*84e33947SAndroid Build Coastguard Worker
ceilOverride(double value)116*84e33947SAndroid Build Coastguard Worker double ceilOverride(double value) {
117*84e33947SAndroid Build Coastguard Worker return ceil(value);
118*84e33947SAndroid Build Coastguard Worker }
119*84e33947SAndroid Build Coastguard Worker
sinOverride(double rad)120*84e33947SAndroid Build Coastguard Worker double sinOverride(double rad) {
121*84e33947SAndroid Build Coastguard Worker return sin(rad);
122*84e33947SAndroid Build Coastguard Worker }
123*84e33947SAndroid Build Coastguard Worker
asinOverride(double val)124*84e33947SAndroid Build Coastguard Worker double asinOverride(double val) {
125*84e33947SAndroid Build Coastguard Worker return asin(val);
126*84e33947SAndroid Build Coastguard Worker }
127*84e33947SAndroid Build Coastguard Worker
atan2Override(double y,double x)128*84e33947SAndroid Build Coastguard Worker double atan2Override(double y, double x) {
129*84e33947SAndroid Build Coastguard Worker return atan2(y, x);
130*84e33947SAndroid Build Coastguard Worker }
131*84e33947SAndroid Build Coastguard Worker
cosOverride(double rad)132*84e33947SAndroid Build Coastguard Worker double cosOverride(double rad) {
133*84e33947SAndroid Build Coastguard Worker return cos(rad);
134*84e33947SAndroid Build Coastguard Worker }
135*84e33947SAndroid Build Coastguard Worker
sqrtOverride(double val)136*84e33947SAndroid Build Coastguard Worker double sqrtOverride(double val) {
137*84e33947SAndroid Build Coastguard Worker return sqrt(val);
138*84e33947SAndroid Build Coastguard Worker }
139*84e33947SAndroid Build Coastguard Worker
roundOverride(double val)140*84e33947SAndroid Build Coastguard Worker double roundOverride(double val) {
141*84e33947SAndroid Build Coastguard Worker return round(val);
142*84e33947SAndroid Build Coastguard Worker }
143*84e33947SAndroid Build Coastguard Worker
144*84e33947SAndroid Build Coastguard Worker // This function is required to be exposed to nanoapps to handle errors from
145*84e33947SAndroid Build Coastguard Worker // invoking virtual functions.
__cxa_pure_virtual(void)146*84e33947SAndroid Build Coastguard Worker void __cxa_pure_virtual(void) {
147*84e33947SAndroid Build Coastguard Worker chreAbort(CHRE_ERROR /* abortCode */);
148*84e33947SAndroid Build Coastguard Worker }
149*84e33947SAndroid Build Coastguard Worker
150*84e33947SAndroid Build Coastguard Worker // TODO(karthikmb/stange): While this array was hand-coded for simple
151*84e33947SAndroid Build Coastguard Worker // "hello-world" prototyping, the list of exported symbols must be
152*84e33947SAndroid Build Coastguard Worker // generated to minimize runtime errors and build breaks.
153*84e33947SAndroid Build Coastguard Worker // clang-format off
154*84e33947SAndroid Build Coastguard Worker // Disable deprecation warning so that deprecated symbols in the array
155*84e33947SAndroid Build Coastguard Worker // can be exported for older nanoapps and tests.
156*84e33947SAndroid Build Coastguard Worker CHRE_DEPRECATED_PREAMBLE
157*84e33947SAndroid Build Coastguard Worker const ExportedData kExportedData[] = {
158*84e33947SAndroid Build Coastguard Worker /* libmath overrides and symbols */
159*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_SYMBOL(asinOverride, "asin"),
160*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_SYMBOL(atan2Override, "atan2"),
161*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_SYMBOL(cosOverride, "cos"),
162*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_SYMBOL(floorOverride, "floor"),
163*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_SYMBOL(ceilOverride, "ceil"),
164*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_SYMBOL(fmaxOverride, "fmax"),
165*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_SYMBOL(fminOverride, "fmin"),
166*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_SYMBOL(frexpOverride, "frexp"),
167*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_SYMBOL(roundOverride, "round"),
168*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_SYMBOL(sinOverride, "sin"),
169*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_SYMBOL(sqrtOverride, "sqrt"),
170*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(acosf),
171*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(asinf),
172*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(atan2f),
173*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(ceilf),
174*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(cosf),
175*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(expf),
176*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(fabsf),
177*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(floorf),
178*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(fmaxf),
179*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(fminf),
180*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(fmodf),
181*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(ldexpf),
182*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(log10f),
183*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(log1pf),
184*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(log2f),
185*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(logf),
186*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(lrintf),
187*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(lroundf),
188*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(powf),
189*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(remainderf),
190*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(roundf),
191*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(sinf),
192*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(sqrtf),
193*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(tanf),
194*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(tanhf),
195*84e33947SAndroid Build Coastguard Worker /* libc overrides and symbols */
196*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(__cxa_pure_virtual),
197*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_SYMBOL(cxaAtexitOverride, "__cxa_atexit"),
198*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_SYMBOL(atexitOverride, "atexit"),
199*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_SYMBOL(deleteOpOverride, "_ZdlPvj"),
200*84e33947SAndroid Build Coastguard Worker #ifdef __clang__
201*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_SYMBOL(deleteOp2Override, "_ZdlPv"),
202*84e33947SAndroid Build Coastguard Worker #endif
203*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(dlsym),
204*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(isgraph),
205*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(memcmp),
206*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(memcpy),
207*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(memmove),
208*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(memset),
209*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(snprintf),
210*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(strcmp),
211*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(strlen),
212*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(strncmp),
213*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(tolower),
214*84e33947SAndroid Build Coastguard Worker /* CHRE symbols */
215*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreAbort),
216*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreAudioConfigureSource),
217*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreAudioGetSource),
218*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreBleGetCapabilities),
219*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreBleGetFilterCapabilities),
220*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreBleFlushAsync),
221*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreBleStartScanAsync),
222*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreBleStartScanAsyncV1_9),
223*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreBleStopScanAsync),
224*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreBleStopScanAsyncV1_9),
225*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreBleReadRssiAsync),
226*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreBleGetScanStatus),
227*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreConfigureDebugDumpEvent),
228*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreConfigureHostSleepStateEvents),
229*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreConfigureNanoappInfoEvents),
230*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreDebugDumpLog),
231*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreGetApiVersion),
232*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreGetCapabilities),
233*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreGetMessageToHostMaxSize),
234*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreGetAppId),
235*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreGetInstanceId),
236*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreGetEstimatedHostTimeOffset),
237*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreGetNanoappInfoByAppId),
238*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreGetNanoappInfoByInstanceId),
239*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreGetPlatformId),
240*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreGetSensorInfo),
241*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreGetSensorSamplingStatus),
242*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreGetTime),
243*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreGetVersion),
244*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreGnssConfigurePassiveLocationListener),
245*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreGnssGetCapabilities),
246*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreGnssLocationSessionStartAsync),
247*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreGnssLocationSessionStopAsync),
248*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreGnssMeasurementSessionStartAsync),
249*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreGnssMeasurementSessionStopAsync),
250*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreHeapAlloc),
251*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreHeapFree),
252*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreIsHostAwake),
253*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreLog),
254*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreSendEvent),
255*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreSendMessageToHost),
256*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreSendMessageToHostEndpoint),
257*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreSendMessageWithPermissions),
258*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreSendReliableMessageAsync),
259*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreSensorConfigure),
260*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreSensorConfigureBiasEvents),
261*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreSensorFind),
262*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreSensorFindDefault),
263*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreSensorFlushAsync),
264*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreSensorGetThreeAxisBias),
265*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreTimerCancel),
266*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreTimerSet),
267*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreUserSettingConfigureEvents),
268*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreUserSettingGetState),
269*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreWifiConfigureScanMonitorAsync),
270*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreWifiGetCapabilities),
271*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreWifiRequestScanAsync),
272*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreWifiRequestRangingAsync),
273*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreWifiNanRequestRangingAsync),
274*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreWifiNanSubscribe),
275*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreWifiNanSubscribeCancel),
276*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreWwanGetCapabilities),
277*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreWwanGetCellInfoAsync),
278*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(platform_chreDebugDumpVaLog),
279*84e33947SAndroid Build Coastguard Worker #ifdef CHRE_NANOAPP_TOKENIZED_LOGGING_SUPPORT_ENABLED
280*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(platform_chrePwTokenizedLog),
281*84e33947SAndroid Build Coastguard Worker #endif // CHRE_NANOAPP_TOKENIZED_LOGGING_SUPPORT_ENABLED
282*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreConfigureHostEndpointNotifications),
283*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chrePublishRpcServices),
284*84e33947SAndroid Build Coastguard Worker ADD_EXPORTED_C_SYMBOL(chreGetHostEndpointInfo),
285*84e33947SAndroid Build Coastguard Worker };
286*84e33947SAndroid Build Coastguard Worker CHRE_DEPRECATED_EPILOGUE
287*84e33947SAndroid Build Coastguard Worker // clang-format on
288*84e33947SAndroid Build Coastguard Worker
289*84e33947SAndroid Build Coastguard Worker } // namespace
290*84e33947SAndroid Build Coastguard Worker
create(void * elfInput,bool mapIntoTcm)291*84e33947SAndroid Build Coastguard Worker NanoappLoader *NanoappLoader::create(void *elfInput, bool mapIntoTcm) {
292*84e33947SAndroid Build Coastguard Worker if (elfInput == nullptr) {
293*84e33947SAndroid Build Coastguard Worker LOGE("Elf header must not be null");
294*84e33947SAndroid Build Coastguard Worker return nullptr;
295*84e33947SAndroid Build Coastguard Worker }
296*84e33947SAndroid Build Coastguard Worker
297*84e33947SAndroid Build Coastguard Worker auto *loader =
298*84e33947SAndroid Build Coastguard Worker static_cast<NanoappLoader *>(memoryAllocDram(sizeof(NanoappLoader)));
299*84e33947SAndroid Build Coastguard Worker if (loader == nullptr) {
300*84e33947SAndroid Build Coastguard Worker LOG_OOM();
301*84e33947SAndroid Build Coastguard Worker return nullptr;
302*84e33947SAndroid Build Coastguard Worker }
303*84e33947SAndroid Build Coastguard Worker new (loader) NanoappLoader(elfInput, mapIntoTcm);
304*84e33947SAndroid Build Coastguard Worker
305*84e33947SAndroid Build Coastguard Worker if (loader->open()) {
306*84e33947SAndroid Build Coastguard Worker return loader;
307*84e33947SAndroid Build Coastguard Worker }
308*84e33947SAndroid Build Coastguard Worker
309*84e33947SAndroid Build Coastguard Worker // Call the destructor explicitly as memoryFreeDram() never calls it.
310*84e33947SAndroid Build Coastguard Worker loader->~NanoappLoader();
311*84e33947SAndroid Build Coastguard Worker memoryFreeDram(loader);
312*84e33947SAndroid Build Coastguard Worker return nullptr;
313*84e33947SAndroid Build Coastguard Worker }
314*84e33947SAndroid Build Coastguard Worker
destroy(NanoappLoader * loader)315*84e33947SAndroid Build Coastguard Worker void NanoappLoader::destroy(NanoappLoader *loader) {
316*84e33947SAndroid Build Coastguard Worker loader->close();
317*84e33947SAndroid Build Coastguard Worker // TODO(b/151847750): Modify utilities to support free'ing from regions other
318*84e33947SAndroid Build Coastguard Worker // than SRAM.
319*84e33947SAndroid Build Coastguard Worker loader->~NanoappLoader();
320*84e33947SAndroid Build Coastguard Worker memoryFreeDram(loader);
321*84e33947SAndroid Build Coastguard Worker }
322*84e33947SAndroid Build Coastguard Worker
findExportedSymbol(const char * name)323*84e33947SAndroid Build Coastguard Worker void *NanoappLoader::findExportedSymbol(const char *name) {
324*84e33947SAndroid Build Coastguard Worker size_t nameLen = strlen(name);
325*84e33947SAndroid Build Coastguard Worker for (size_t i = 0; i < ARRAY_SIZE(kExportedData); i++) {
326*84e33947SAndroid Build Coastguard Worker if (nameLen == strlen(kExportedData[i].dataName) &&
327*84e33947SAndroid Build Coastguard Worker strncmp(name, kExportedData[i].dataName, nameLen) == 0) {
328*84e33947SAndroid Build Coastguard Worker return kExportedData[i].data;
329*84e33947SAndroid Build Coastguard Worker }
330*84e33947SAndroid Build Coastguard Worker }
331*84e33947SAndroid Build Coastguard Worker
332*84e33947SAndroid Build Coastguard Worker #ifdef CHREX_SYMBOL_EXTENSIONS
333*84e33947SAndroid Build Coastguard Worker for (size_t i = 0; i < ARRAY_SIZE(kVendorExportedData); i++) {
334*84e33947SAndroid Build Coastguard Worker if (nameLen == strlen(kVendorExportedData[i].dataName) &&
335*84e33947SAndroid Build Coastguard Worker strncmp(name, kVendorExportedData[i].dataName, nameLen) == 0) {
336*84e33947SAndroid Build Coastguard Worker return kVendorExportedData[i].data;
337*84e33947SAndroid Build Coastguard Worker }
338*84e33947SAndroid Build Coastguard Worker }
339*84e33947SAndroid Build Coastguard Worker #endif
340*84e33947SAndroid Build Coastguard Worker
341*84e33947SAndroid Build Coastguard Worker return nullptr;
342*84e33947SAndroid Build Coastguard Worker }
343*84e33947SAndroid Build Coastguard Worker
open()344*84e33947SAndroid Build Coastguard Worker bool NanoappLoader::open() {
345*84e33947SAndroid Build Coastguard Worker if (!copyAndVerifyHeaders()) {
346*84e33947SAndroid Build Coastguard Worker LOGE("Failed to copy and verify elf headers");
347*84e33947SAndroid Build Coastguard Worker } else if (!createMappings()) {
348*84e33947SAndroid Build Coastguard Worker LOGE("Failed to create mappings");
349*84e33947SAndroid Build Coastguard Worker } else if (!fixRelocations()) {
350*84e33947SAndroid Build Coastguard Worker LOGE("Failed to fix relocations");
351*84e33947SAndroid Build Coastguard Worker } else if (!resolveGot()) {
352*84e33947SAndroid Build Coastguard Worker LOGE("Failed to resolve GOT");
353*84e33947SAndroid Build Coastguard Worker } else {
354*84e33947SAndroid Build Coastguard Worker // Wipe caches before calling init array to ensure initializers are not in
355*84e33947SAndroid Build Coastguard Worker // the data cache.
356*84e33947SAndroid Build Coastguard Worker wipeSystemCaches(reinterpret_cast<uintptr_t>(mMapping), mMemorySpan);
357*84e33947SAndroid Build Coastguard Worker if (!callInitArray()) {
358*84e33947SAndroid Build Coastguard Worker LOGE("Failed to perform static init");
359*84e33947SAndroid Build Coastguard Worker } else {
360*84e33947SAndroid Build Coastguard Worker return true;
361*84e33947SAndroid Build Coastguard Worker }
362*84e33947SAndroid Build Coastguard Worker }
363*84e33947SAndroid Build Coastguard Worker freeAllocatedData();
364*84e33947SAndroid Build Coastguard Worker return false;
365*84e33947SAndroid Build Coastguard Worker }
366*84e33947SAndroid Build Coastguard Worker
close()367*84e33947SAndroid Build Coastguard Worker void NanoappLoader::close() {
368*84e33947SAndroid Build Coastguard Worker callAtexitFunctions();
369*84e33947SAndroid Build Coastguard Worker callTerminatorArray();
370*84e33947SAndroid Build Coastguard Worker freeAllocatedData();
371*84e33947SAndroid Build Coastguard Worker }
372*84e33947SAndroid Build Coastguard Worker
findSymbolByName(const char * name)373*84e33947SAndroid Build Coastguard Worker void *NanoappLoader::findSymbolByName(const char *name) {
374*84e33947SAndroid Build Coastguard Worker for (size_t offset = 0; offset < mDynamicSymbolTableSize;
375*84e33947SAndroid Build Coastguard Worker offset += sizeof(ElfSym)) {
376*84e33947SAndroid Build Coastguard Worker ElfSym *currSym =
377*84e33947SAndroid Build Coastguard Worker reinterpret_cast<ElfSym *>(mDynamicSymbolTablePtr + offset);
378*84e33947SAndroid Build Coastguard Worker const char *symbolName = getDataName(currSym);
379*84e33947SAndroid Build Coastguard Worker
380*84e33947SAndroid Build Coastguard Worker if (strncmp(symbolName, name, strlen(name)) == 0) {
381*84e33947SAndroid Build Coastguard Worker return getSymbolTarget(currSym);
382*84e33947SAndroid Build Coastguard Worker }
383*84e33947SAndroid Build Coastguard Worker }
384*84e33947SAndroid Build Coastguard Worker return nullptr;
385*84e33947SAndroid Build Coastguard Worker }
386*84e33947SAndroid Build Coastguard Worker
registerAtexitFunction(struct AtExitCallback & cb)387*84e33947SAndroid Build Coastguard Worker void NanoappLoader::registerAtexitFunction(struct AtExitCallback &cb) {
388*84e33947SAndroid Build Coastguard Worker if (!mAtexitFunctions.push_back(cb)) {
389*84e33947SAndroid Build Coastguard Worker LOG_OOM();
390*84e33947SAndroid Build Coastguard Worker gStaticInitFailure = true;
391*84e33947SAndroid Build Coastguard Worker }
392*84e33947SAndroid Build Coastguard Worker }
393*84e33947SAndroid Build Coastguard Worker
mapBss(const ProgramHeader * hdr)394*84e33947SAndroid Build Coastguard Worker void NanoappLoader::mapBss(const ProgramHeader *hdr) {
395*84e33947SAndroid Build Coastguard Worker // if the memory size of this segment exceeds the file size zero fill the
396*84e33947SAndroid Build Coastguard Worker // difference.
397*84e33947SAndroid Build Coastguard Worker LOGV("Program Hdr mem sz: %u file size: %u", hdr->p_memsz, hdr->p_filesz);
398*84e33947SAndroid Build Coastguard Worker if (hdr->p_memsz > hdr->p_filesz) {
399*84e33947SAndroid Build Coastguard Worker ElfAddr endOfFile = hdr->p_vaddr + hdr->p_filesz + mLoadBias;
400*84e33947SAndroid Build Coastguard Worker ElfAddr endOfMem = hdr->p_vaddr + hdr->p_memsz + mLoadBias;
401*84e33947SAndroid Build Coastguard Worker if (endOfMem > endOfFile) {
402*84e33947SAndroid Build Coastguard Worker auto deltaMem = endOfMem - endOfFile;
403*84e33947SAndroid Build Coastguard Worker LOGV("Zeroing out %u from page %x", deltaMem, endOfFile);
404*84e33947SAndroid Build Coastguard Worker memset(reinterpret_cast<void *>(endOfFile), 0, deltaMem);
405*84e33947SAndroid Build Coastguard Worker }
406*84e33947SAndroid Build Coastguard Worker }
407*84e33947SAndroid Build Coastguard Worker }
408*84e33947SAndroid Build Coastguard Worker
callInitArray()409*84e33947SAndroid Build Coastguard Worker bool NanoappLoader::callInitArray() {
410*84e33947SAndroid Build Coastguard Worker bool success = true;
411*84e33947SAndroid Build Coastguard Worker // Sets global variable used by atexit in case it's invoked as part of
412*84e33947SAndroid Build Coastguard Worker // initializing static data.
413*84e33947SAndroid Build Coastguard Worker gCurrentlyLoadingNanoapp = this;
414*84e33947SAndroid Build Coastguard Worker
415*84e33947SAndroid Build Coastguard Worker // TODO(b/151847750): ELF can have other sections like .init, .preinit, .fini
416*84e33947SAndroid Build Coastguard Worker // etc. Be sure to look for those if they end up being something that should
417*84e33947SAndroid Build Coastguard Worker // be supported for nanoapps.
418*84e33947SAndroid Build Coastguard Worker for (size_t i = 0; i < mNumSectionHeaders; ++i) {
419*84e33947SAndroid Build Coastguard Worker const char *name = getSectionHeaderName(mSectionHeadersPtr[i].sh_name);
420*84e33947SAndroid Build Coastguard Worker if (strncmp(name, kInitArrayName, strlen(kInitArrayName)) == 0) {
421*84e33947SAndroid Build Coastguard Worker LOGV("Invoking init function");
422*84e33947SAndroid Build Coastguard Worker uintptr_t initArray =
423*84e33947SAndroid Build Coastguard Worker static_cast<uintptr_t>(mLoadBias + mSectionHeadersPtr[i].sh_addr);
424*84e33947SAndroid Build Coastguard Worker uintptr_t offset = 0;
425*84e33947SAndroid Build Coastguard Worker while (offset < mSectionHeadersPtr[i].sh_size) {
426*84e33947SAndroid Build Coastguard Worker ElfAddr *funcPtr = reinterpret_cast<ElfAddr *>(initArray + offset);
427*84e33947SAndroid Build Coastguard Worker uintptr_t initFunction = static_cast<uintptr_t>(*funcPtr);
428*84e33947SAndroid Build Coastguard Worker ((void (*)())initFunction)();
429*84e33947SAndroid Build Coastguard Worker offset += sizeof(initFunction);
430*84e33947SAndroid Build Coastguard Worker if (gStaticInitFailure) {
431*84e33947SAndroid Build Coastguard Worker success = false;
432*84e33947SAndroid Build Coastguard Worker break;
433*84e33947SAndroid Build Coastguard Worker }
434*84e33947SAndroid Build Coastguard Worker }
435*84e33947SAndroid Build Coastguard Worker break;
436*84e33947SAndroid Build Coastguard Worker }
437*84e33947SAndroid Build Coastguard Worker }
438*84e33947SAndroid Build Coastguard Worker
439*84e33947SAndroid Build Coastguard Worker //! Reset global state so it doesn't leak into the next load.
440*84e33947SAndroid Build Coastguard Worker gCurrentlyLoadingNanoapp = nullptr;
441*84e33947SAndroid Build Coastguard Worker gStaticInitFailure = false;
442*84e33947SAndroid Build Coastguard Worker return success;
443*84e33947SAndroid Build Coastguard Worker }
444*84e33947SAndroid Build Coastguard Worker
roundDownToAlign(uintptr_t virtualAddr,size_t alignment)445*84e33947SAndroid Build Coastguard Worker uintptr_t NanoappLoader::roundDownToAlign(uintptr_t virtualAddr,
446*84e33947SAndroid Build Coastguard Worker size_t alignment) {
447*84e33947SAndroid Build Coastguard Worker return alignment == 0 ? virtualAddr : virtualAddr & -alignment;
448*84e33947SAndroid Build Coastguard Worker }
449*84e33947SAndroid Build Coastguard Worker
freeAllocatedData()450*84e33947SAndroid Build Coastguard Worker void NanoappLoader::freeAllocatedData() {
451*84e33947SAndroid Build Coastguard Worker if (mIsTcmBinary) {
452*84e33947SAndroid Build Coastguard Worker nanoappBinaryFree(mMapping);
453*84e33947SAndroid Build Coastguard Worker } else {
454*84e33947SAndroid Build Coastguard Worker nanoappBinaryDramFree(mMapping);
455*84e33947SAndroid Build Coastguard Worker }
456*84e33947SAndroid Build Coastguard Worker memoryFreeDram(mSectionHeadersPtr);
457*84e33947SAndroid Build Coastguard Worker memoryFreeDram(mSectionNamesPtr);
458*84e33947SAndroid Build Coastguard Worker mDynamicSymbolTablePtr = nullptr;
459*84e33947SAndroid Build Coastguard Worker mDynamicSymbolTableSize = 0;
460*84e33947SAndroid Build Coastguard Worker }
461*84e33947SAndroid Build Coastguard Worker
verifyElfHeader()462*84e33947SAndroid Build Coastguard Worker bool NanoappLoader::verifyElfHeader() {
463*84e33947SAndroid Build Coastguard Worker ElfHeader *elfHeader = getElfHeader();
464*84e33947SAndroid Build Coastguard Worker if (elfHeader != nullptr && (elfHeader->e_ident[EI_MAG0] == ELFMAG0) &&
465*84e33947SAndroid Build Coastguard Worker (elfHeader->e_ident[EI_MAG1] == ELFMAG1) &&
466*84e33947SAndroid Build Coastguard Worker (elfHeader->e_ident[EI_MAG2] == ELFMAG2) &&
467*84e33947SAndroid Build Coastguard Worker (elfHeader->e_ident[EI_MAG3] == ELFMAG3) &&
468*84e33947SAndroid Build Coastguard Worker (elfHeader->e_ehsize == sizeof(ElfHeader)) &&
469*84e33947SAndroid Build Coastguard Worker (elfHeader->e_phentsize == sizeof(ProgramHeader)) &&
470*84e33947SAndroid Build Coastguard Worker (elfHeader->e_shentsize == sizeof(SectionHeader)) &&
471*84e33947SAndroid Build Coastguard Worker (elfHeader->e_shstrndx < elfHeader->e_shnum) &&
472*84e33947SAndroid Build Coastguard Worker (elfHeader->e_version == EV_CURRENT) &&
473*84e33947SAndroid Build Coastguard Worker (elfHeader->e_machine == CHRE_LOADER_ARCH) &&
474*84e33947SAndroid Build Coastguard Worker (elfHeader->e_type == ET_DYN)) {
475*84e33947SAndroid Build Coastguard Worker return true;
476*84e33947SAndroid Build Coastguard Worker }
477*84e33947SAndroid Build Coastguard Worker return false;
478*84e33947SAndroid Build Coastguard Worker }
479*84e33947SAndroid Build Coastguard Worker
verifyProgramHeaders()480*84e33947SAndroid Build Coastguard Worker bool NanoappLoader::verifyProgramHeaders() {
481*84e33947SAndroid Build Coastguard Worker // This is a minimal check for now -
482*84e33947SAndroid Build Coastguard Worker // there should be at least one load segment.
483*84e33947SAndroid Build Coastguard Worker for (size_t i = 0; i < getProgramHeaderArraySize(); ++i) {
484*84e33947SAndroid Build Coastguard Worker if (getProgramHeaderArray()[i].p_type == PT_LOAD) {
485*84e33947SAndroid Build Coastguard Worker return true;
486*84e33947SAndroid Build Coastguard Worker }
487*84e33947SAndroid Build Coastguard Worker }
488*84e33947SAndroid Build Coastguard Worker LOGE("No load segment found");
489*84e33947SAndroid Build Coastguard Worker return false;
490*84e33947SAndroid Build Coastguard Worker }
491*84e33947SAndroid Build Coastguard Worker
getSectionHeaderName(size_t headerOffset)492*84e33947SAndroid Build Coastguard Worker const char *NanoappLoader::getSectionHeaderName(size_t headerOffset) {
493*84e33947SAndroid Build Coastguard Worker if (headerOffset == 0) {
494*84e33947SAndroid Build Coastguard Worker return "";
495*84e33947SAndroid Build Coastguard Worker }
496*84e33947SAndroid Build Coastguard Worker
497*84e33947SAndroid Build Coastguard Worker return &mSectionNamesPtr[headerOffset];
498*84e33947SAndroid Build Coastguard Worker }
499*84e33947SAndroid Build Coastguard Worker
getSectionHeader(const char * headerName)500*84e33947SAndroid Build Coastguard Worker NanoappLoader::SectionHeader *NanoappLoader::getSectionHeader(
501*84e33947SAndroid Build Coastguard Worker const char *headerName) {
502*84e33947SAndroid Build Coastguard Worker SectionHeader *rv = nullptr;
503*84e33947SAndroid Build Coastguard Worker for (size_t i = 0; i < mNumSectionHeaders; ++i) {
504*84e33947SAndroid Build Coastguard Worker const char *name = getSectionHeaderName(mSectionHeadersPtr[i].sh_name);
505*84e33947SAndroid Build Coastguard Worker if (strncmp(name, headerName, strlen(headerName)) == 0) {
506*84e33947SAndroid Build Coastguard Worker rv = &mSectionHeadersPtr[i];
507*84e33947SAndroid Build Coastguard Worker break;
508*84e33947SAndroid Build Coastguard Worker }
509*84e33947SAndroid Build Coastguard Worker }
510*84e33947SAndroid Build Coastguard Worker return rv;
511*84e33947SAndroid Build Coastguard Worker }
512*84e33947SAndroid Build Coastguard Worker
getProgramHeaderArray()513*84e33947SAndroid Build Coastguard Worker ProgramHeader *NanoappLoader::getProgramHeaderArray() {
514*84e33947SAndroid Build Coastguard Worker return reinterpret_cast<ProgramHeader *>(mBinary + getElfHeader()->e_phoff);
515*84e33947SAndroid Build Coastguard Worker }
516*84e33947SAndroid Build Coastguard Worker
getProgramHeaderArraySize()517*84e33947SAndroid Build Coastguard Worker size_t NanoappLoader::getProgramHeaderArraySize() {
518*84e33947SAndroid Build Coastguard Worker return getElfHeader()->e_phnum;
519*84e33947SAndroid Build Coastguard Worker }
520*84e33947SAndroid Build Coastguard Worker
verifyDynamicTables()521*84e33947SAndroid Build Coastguard Worker bool NanoappLoader::verifyDynamicTables() {
522*84e33947SAndroid Build Coastguard Worker SectionHeader *dynamicStringTablePtr = getSectionHeader(kDynstrTableName);
523*84e33947SAndroid Build Coastguard Worker if (dynamicStringTablePtr == nullptr) {
524*84e33947SAndroid Build Coastguard Worker LOGE("Failed to find table %s", kDynstrTableName);
525*84e33947SAndroid Build Coastguard Worker return false;
526*84e33947SAndroid Build Coastguard Worker }
527*84e33947SAndroid Build Coastguard Worker mDynamicStringTablePtr =
528*84e33947SAndroid Build Coastguard Worker reinterpret_cast<char *>(mBinary + dynamicStringTablePtr->sh_offset);
529*84e33947SAndroid Build Coastguard Worker
530*84e33947SAndroid Build Coastguard Worker SectionHeader *dynamicSymbolTablePtr = getSectionHeader(kDynsymTableName);
531*84e33947SAndroid Build Coastguard Worker if (dynamicSymbolTablePtr == nullptr) {
532*84e33947SAndroid Build Coastguard Worker LOGE("Failed to find table %s", kDynsymTableName);
533*84e33947SAndroid Build Coastguard Worker return false;
534*84e33947SAndroid Build Coastguard Worker }
535*84e33947SAndroid Build Coastguard Worker mDynamicSymbolTablePtr = (mBinary + dynamicSymbolTablePtr->sh_offset);
536*84e33947SAndroid Build Coastguard Worker mDynamicSymbolTableSize = dynamicSymbolTablePtr->sh_size;
537*84e33947SAndroid Build Coastguard Worker
538*84e33947SAndroid Build Coastguard Worker return true;
539*84e33947SAndroid Build Coastguard Worker }
540*84e33947SAndroid Build Coastguard Worker
copyAndVerifyHeaders()541*84e33947SAndroid Build Coastguard Worker bool NanoappLoader::copyAndVerifyHeaders() {
542*84e33947SAndroid Build Coastguard Worker // Verify the ELF Header
543*84e33947SAndroid Build Coastguard Worker if (!verifyElfHeader()) {
544*84e33947SAndroid Build Coastguard Worker LOGE("ELF header is invalid");
545*84e33947SAndroid Build Coastguard Worker return false;
546*84e33947SAndroid Build Coastguard Worker }
547*84e33947SAndroid Build Coastguard Worker
548*84e33947SAndroid Build Coastguard Worker // Verify Program Headers
549*84e33947SAndroid Build Coastguard Worker if (!verifyProgramHeaders()) {
550*84e33947SAndroid Build Coastguard Worker LOGE("Program headers are invalid");
551*84e33947SAndroid Build Coastguard Worker return false;
552*84e33947SAndroid Build Coastguard Worker }
553*84e33947SAndroid Build Coastguard Worker
554*84e33947SAndroid Build Coastguard Worker // Load Section Headers
555*84e33947SAndroid Build Coastguard Worker ElfHeader *elfHeader = getElfHeader();
556*84e33947SAndroid Build Coastguard Worker size_t sectionHeaderSizeBytes = sizeof(SectionHeader) * elfHeader->e_shnum;
557*84e33947SAndroid Build Coastguard Worker mSectionHeadersPtr =
558*84e33947SAndroid Build Coastguard Worker static_cast<SectionHeader *>(memoryAllocDram(sectionHeaderSizeBytes));
559*84e33947SAndroid Build Coastguard Worker if (mSectionHeadersPtr == nullptr) {
560*84e33947SAndroid Build Coastguard Worker LOG_OOM();
561*84e33947SAndroid Build Coastguard Worker return false;
562*84e33947SAndroid Build Coastguard Worker }
563*84e33947SAndroid Build Coastguard Worker memcpy(mSectionHeadersPtr, (mBinary + elfHeader->e_shoff),
564*84e33947SAndroid Build Coastguard Worker sectionHeaderSizeBytes);
565*84e33947SAndroid Build Coastguard Worker mNumSectionHeaders = elfHeader->e_shnum;
566*84e33947SAndroid Build Coastguard Worker
567*84e33947SAndroid Build Coastguard Worker // Load section header names
568*84e33947SAndroid Build Coastguard Worker SectionHeader &stringSection = mSectionHeadersPtr[elfHeader->e_shstrndx];
569*84e33947SAndroid Build Coastguard Worker size_t sectionSize = stringSection.sh_size;
570*84e33947SAndroid Build Coastguard Worker mSectionNamesPtr = static_cast<char *>(memoryAllocDram(sectionSize));
571*84e33947SAndroid Build Coastguard Worker if (mSectionNamesPtr == nullptr) {
572*84e33947SAndroid Build Coastguard Worker LOG_OOM();
573*84e33947SAndroid Build Coastguard Worker return false;
574*84e33947SAndroid Build Coastguard Worker }
575*84e33947SAndroid Build Coastguard Worker memcpy(mSectionNamesPtr, mBinary + stringSection.sh_offset, sectionSize);
576*84e33947SAndroid Build Coastguard Worker
577*84e33947SAndroid Build Coastguard Worker // Verify dynamic symbol table
578*84e33947SAndroid Build Coastguard Worker if (!verifyDynamicTables()) {
579*84e33947SAndroid Build Coastguard Worker LOGE("Failed to verify dynamic tables");
580*84e33947SAndroid Build Coastguard Worker return false;
581*84e33947SAndroid Build Coastguard Worker }
582*84e33947SAndroid Build Coastguard Worker
583*84e33947SAndroid Build Coastguard Worker return true;
584*84e33947SAndroid Build Coastguard Worker }
585*84e33947SAndroid Build Coastguard Worker
createMappings()586*84e33947SAndroid Build Coastguard Worker bool NanoappLoader::createMappings() {
587*84e33947SAndroid Build Coastguard Worker // ELF needs pt_load segments to be in contiguous ascending order of
588*84e33947SAndroid Build Coastguard Worker // virtual addresses. So the first and last segs can be used to
589*84e33947SAndroid Build Coastguard Worker // calculate the entire address span of the image.
590*84e33947SAndroid Build Coastguard Worker ProgramHeader *programHeaderArray = getProgramHeaderArray();
591*84e33947SAndroid Build Coastguard Worker size_t numProgramHeaders = getProgramHeaderArraySize();
592*84e33947SAndroid Build Coastguard Worker const ProgramHeader *first = &programHeaderArray[0];
593*84e33947SAndroid Build Coastguard Worker const ProgramHeader *last = &programHeaderArray[numProgramHeaders - 1];
594*84e33947SAndroid Build Coastguard Worker
595*84e33947SAndroid Build Coastguard Worker // Find first load segment
596*84e33947SAndroid Build Coastguard Worker while (first->p_type != PT_LOAD && first <= last) {
597*84e33947SAndroid Build Coastguard Worker ++first;
598*84e33947SAndroid Build Coastguard Worker }
599*84e33947SAndroid Build Coastguard Worker
600*84e33947SAndroid Build Coastguard Worker bool success = false;
601*84e33947SAndroid Build Coastguard Worker if (first->p_type != PT_LOAD) {
602*84e33947SAndroid Build Coastguard Worker LOGE("Unable to find any load segments in the binary");
603*84e33947SAndroid Build Coastguard Worker } else {
604*84e33947SAndroid Build Coastguard Worker // Verify that the first load segment has a program header
605*84e33947SAndroid Build Coastguard Worker // first byte of a valid load segment can't be greater than the
606*84e33947SAndroid Build Coastguard Worker // program header offset
607*84e33947SAndroid Build Coastguard Worker bool valid =
608*84e33947SAndroid Build Coastguard Worker (first->p_offset < getElfHeader()->e_phoff) &&
609*84e33947SAndroid Build Coastguard Worker (first->p_filesz >= (getElfHeader()->e_phoff +
610*84e33947SAndroid Build Coastguard Worker (numProgramHeaders * sizeof(ProgramHeader))));
611*84e33947SAndroid Build Coastguard Worker if (!valid) {
612*84e33947SAndroid Build Coastguard Worker LOGE("Load segment program header validation failed");
613*84e33947SAndroid Build Coastguard Worker } else {
614*84e33947SAndroid Build Coastguard Worker // Get the last load segment
615*84e33947SAndroid Build Coastguard Worker while (last > first && last->p_type != PT_LOAD) --last;
616*84e33947SAndroid Build Coastguard Worker
617*84e33947SAndroid Build Coastguard Worker size_t alignment = first->p_align;
618*84e33947SAndroid Build Coastguard Worker size_t memorySpan = last->p_vaddr + last->p_memsz - first->p_vaddr;
619*84e33947SAndroid Build Coastguard Worker LOGV("Nanoapp image Memory Span: %zu", memorySpan);
620*84e33947SAndroid Build Coastguard Worker
621*84e33947SAndroid Build Coastguard Worker if (mIsTcmBinary) {
622*84e33947SAndroid Build Coastguard Worker mMapping =
623*84e33947SAndroid Build Coastguard Worker static_cast<uint8_t *>(nanoappBinaryAlloc(memorySpan, alignment));
624*84e33947SAndroid Build Coastguard Worker } else {
625*84e33947SAndroid Build Coastguard Worker mMapping = static_cast<uint8_t *>(
626*84e33947SAndroid Build Coastguard Worker nanoappBinaryDramAlloc(memorySpan, alignment));
627*84e33947SAndroid Build Coastguard Worker }
628*84e33947SAndroid Build Coastguard Worker
629*84e33947SAndroid Build Coastguard Worker if (mMapping == nullptr) {
630*84e33947SAndroid Build Coastguard Worker LOG_OOM();
631*84e33947SAndroid Build Coastguard Worker } else {
632*84e33947SAndroid Build Coastguard Worker LOGV("Starting location of mappings %p", mMapping);
633*84e33947SAndroid Build Coastguard Worker mMemorySpan = memorySpan;
634*84e33947SAndroid Build Coastguard Worker
635*84e33947SAndroid Build Coastguard Worker // Calculate the load bias using the first load segment.
636*84e33947SAndroid Build Coastguard Worker uintptr_t adjustedFirstLoadSegAddr =
637*84e33947SAndroid Build Coastguard Worker roundDownToAlign(first->p_vaddr, alignment);
638*84e33947SAndroid Build Coastguard Worker mLoadBias =
639*84e33947SAndroid Build Coastguard Worker reinterpret_cast<uintptr_t>(mMapping) - adjustedFirstLoadSegAddr;
640*84e33947SAndroid Build Coastguard Worker LOGV("Load bias is %lu", static_cast<long unsigned int>(mLoadBias));
641*84e33947SAndroid Build Coastguard Worker
642*84e33947SAndroid Build Coastguard Worker success = true;
643*84e33947SAndroid Build Coastguard Worker }
644*84e33947SAndroid Build Coastguard Worker }
645*84e33947SAndroid Build Coastguard Worker }
646*84e33947SAndroid Build Coastguard Worker
647*84e33947SAndroid Build Coastguard Worker if (success) {
648*84e33947SAndroid Build Coastguard Worker // Map the remaining segments
649*84e33947SAndroid Build Coastguard Worker for (const ProgramHeader *ph = first; ph <= last; ++ph) {
650*84e33947SAndroid Build Coastguard Worker if (ph->p_type == PT_LOAD) {
651*84e33947SAndroid Build Coastguard Worker ElfAddr segStart = ph->p_vaddr + mLoadBias;
652*84e33947SAndroid Build Coastguard Worker void *startPage = reinterpret_cast<void *>(segStart);
653*84e33947SAndroid Build Coastguard Worker void *binaryStartPage = mBinary + ph->p_offset;
654*84e33947SAndroid Build Coastguard Worker size_t segmentLen = ph->p_filesz;
655*84e33947SAndroid Build Coastguard Worker
656*84e33947SAndroid Build Coastguard Worker LOGV("Mapping start page %p from %p with length %zu", startPage,
657*84e33947SAndroid Build Coastguard Worker binaryStartPage, segmentLen);
658*84e33947SAndroid Build Coastguard Worker memcpy(startPage, binaryStartPage, segmentLen);
659*84e33947SAndroid Build Coastguard Worker mapBss(ph);
660*84e33947SAndroid Build Coastguard Worker } else {
661*84e33947SAndroid Build Coastguard Worker LOGE("Non-load segment found between load segments");
662*84e33947SAndroid Build Coastguard Worker success = false;
663*84e33947SAndroid Build Coastguard Worker break;
664*84e33947SAndroid Build Coastguard Worker }
665*84e33947SAndroid Build Coastguard Worker }
666*84e33947SAndroid Build Coastguard Worker }
667*84e33947SAndroid Build Coastguard Worker
668*84e33947SAndroid Build Coastguard Worker return success;
669*84e33947SAndroid Build Coastguard Worker }
670*84e33947SAndroid Build Coastguard Worker
getDynamicSymbol(size_t posInSymbolTable)671*84e33947SAndroid Build Coastguard Worker NanoappLoader::ElfSym *NanoappLoader::getDynamicSymbol(
672*84e33947SAndroid Build Coastguard Worker size_t posInSymbolTable) {
673*84e33947SAndroid Build Coastguard Worker size_t numElements = mDynamicSymbolTableSize / sizeof(ElfSym);
674*84e33947SAndroid Build Coastguard Worker CHRE_ASSERT(posInSymbolTable < numElements);
675*84e33947SAndroid Build Coastguard Worker if (posInSymbolTable < numElements) {
676*84e33947SAndroid Build Coastguard Worker return reinterpret_cast<ElfSym *>(
677*84e33947SAndroid Build Coastguard Worker &mDynamicSymbolTablePtr[posInSymbolTable * sizeof(ElfSym)]);
678*84e33947SAndroid Build Coastguard Worker }
679*84e33947SAndroid Build Coastguard Worker LOGE("Symbol index %zu is out of bound %zu", posInSymbolTable, numElements);
680*84e33947SAndroid Build Coastguard Worker return nullptr;
681*84e33947SAndroid Build Coastguard Worker }
682*84e33947SAndroid Build Coastguard Worker
getDataName(const ElfSym * symbol)683*84e33947SAndroid Build Coastguard Worker const char *NanoappLoader::getDataName(const ElfSym *symbol) {
684*84e33947SAndroid Build Coastguard Worker return symbol == nullptr ? nullptr : &mDynamicStringTablePtr[symbol->st_name];
685*84e33947SAndroid Build Coastguard Worker }
686*84e33947SAndroid Build Coastguard Worker
getSymbolTarget(const ElfSym * symbol)687*84e33947SAndroid Build Coastguard Worker void *NanoappLoader::getSymbolTarget(const ElfSym *symbol) {
688*84e33947SAndroid Build Coastguard Worker if (symbol == nullptr || symbol->st_shndx == SHN_UNDEF) {
689*84e33947SAndroid Build Coastguard Worker return nullptr;
690*84e33947SAndroid Build Coastguard Worker }
691*84e33947SAndroid Build Coastguard Worker return mMapping + symbol->st_value;
692*84e33947SAndroid Build Coastguard Worker }
693*84e33947SAndroid Build Coastguard Worker
resolveData(size_t posInSymbolTable)694*84e33947SAndroid Build Coastguard Worker void *NanoappLoader::resolveData(size_t posInSymbolTable) {
695*84e33947SAndroid Build Coastguard Worker const ElfSym *symbol = getDynamicSymbol(posInSymbolTable);
696*84e33947SAndroid Build Coastguard Worker const char *dataName = getDataName(symbol);
697*84e33947SAndroid Build Coastguard Worker void *target = nullptr;
698*84e33947SAndroid Build Coastguard Worker
699*84e33947SAndroid Build Coastguard Worker if (dataName != nullptr) {
700*84e33947SAndroid Build Coastguard Worker LOGV("Resolving %s", dataName);
701*84e33947SAndroid Build Coastguard Worker target = findExportedSymbol(dataName);
702*84e33947SAndroid Build Coastguard Worker if (target == nullptr) {
703*84e33947SAndroid Build Coastguard Worker target = getSymbolTarget(symbol);
704*84e33947SAndroid Build Coastguard Worker }
705*84e33947SAndroid Build Coastguard Worker if (target == nullptr) {
706*84e33947SAndroid Build Coastguard Worker LOGE("Unable to find %s", dataName);
707*84e33947SAndroid Build Coastguard Worker }
708*84e33947SAndroid Build Coastguard Worker }
709*84e33947SAndroid Build Coastguard Worker
710*84e33947SAndroid Build Coastguard Worker return target;
711*84e33947SAndroid Build Coastguard Worker }
712*84e33947SAndroid Build Coastguard Worker
getDynamicHeader()713*84e33947SAndroid Build Coastguard Worker NanoappLoader::DynamicHeader *NanoappLoader::getDynamicHeader() {
714*84e33947SAndroid Build Coastguard Worker DynamicHeader *dyn = nullptr;
715*84e33947SAndroid Build Coastguard Worker ProgramHeader *programHeaders = getProgramHeaderArray();
716*84e33947SAndroid Build Coastguard Worker for (size_t i = 0; i < getProgramHeaderArraySize(); ++i) {
717*84e33947SAndroid Build Coastguard Worker if (programHeaders[i].p_type == PT_DYNAMIC) {
718*84e33947SAndroid Build Coastguard Worker dyn = reinterpret_cast<DynamicHeader *>(programHeaders[i].p_offset +
719*84e33947SAndroid Build Coastguard Worker mBinary);
720*84e33947SAndroid Build Coastguard Worker break;
721*84e33947SAndroid Build Coastguard Worker }
722*84e33947SAndroid Build Coastguard Worker }
723*84e33947SAndroid Build Coastguard Worker return dyn;
724*84e33947SAndroid Build Coastguard Worker }
725*84e33947SAndroid Build Coastguard Worker
getFirstRoSegHeader()726*84e33947SAndroid Build Coastguard Worker NanoappLoader::ProgramHeader *NanoappLoader::getFirstRoSegHeader() {
727*84e33947SAndroid Build Coastguard Worker // return the first read only segment found
728*84e33947SAndroid Build Coastguard Worker ProgramHeader *ro = nullptr;
729*84e33947SAndroid Build Coastguard Worker ProgramHeader *programHeaders = getProgramHeaderArray();
730*84e33947SAndroid Build Coastguard Worker for (size_t i = 0; i < getProgramHeaderArraySize(); ++i) {
731*84e33947SAndroid Build Coastguard Worker if (!(programHeaders[i].p_flags & PF_W)) {
732*84e33947SAndroid Build Coastguard Worker ro = &programHeaders[i];
733*84e33947SAndroid Build Coastguard Worker break;
734*84e33947SAndroid Build Coastguard Worker }
735*84e33947SAndroid Build Coastguard Worker }
736*84e33947SAndroid Build Coastguard Worker return ro;
737*84e33947SAndroid Build Coastguard Worker }
738*84e33947SAndroid Build Coastguard Worker
getDynEntry(DynamicHeader * dyn,int field)739*84e33947SAndroid Build Coastguard Worker NanoappLoader::ElfWord NanoappLoader::getDynEntry(DynamicHeader *dyn,
740*84e33947SAndroid Build Coastguard Worker int field) {
741*84e33947SAndroid Build Coastguard Worker ElfWord rv = 0;
742*84e33947SAndroid Build Coastguard Worker
743*84e33947SAndroid Build Coastguard Worker while (dyn->d_tag != DT_NULL) {
744*84e33947SAndroid Build Coastguard Worker if (dyn->d_tag == field) {
745*84e33947SAndroid Build Coastguard Worker rv = dyn->d_un.d_val;
746*84e33947SAndroid Build Coastguard Worker break;
747*84e33947SAndroid Build Coastguard Worker }
748*84e33947SAndroid Build Coastguard Worker ++dyn;
749*84e33947SAndroid Build Coastguard Worker }
750*84e33947SAndroid Build Coastguard Worker
751*84e33947SAndroid Build Coastguard Worker return rv;
752*84e33947SAndroid Build Coastguard Worker }
753*84e33947SAndroid Build Coastguard Worker
fixRelocations()754*84e33947SAndroid Build Coastguard Worker bool NanoappLoader::fixRelocations() {
755*84e33947SAndroid Build Coastguard Worker DynamicHeader *dyn = getDynamicHeader();
756*84e33947SAndroid Build Coastguard Worker if (dyn == nullptr) {
757*84e33947SAndroid Build Coastguard Worker LOGE("Dynamic headers are missing from shared object");
758*84e33947SAndroid Build Coastguard Worker }
759*84e33947SAndroid Build Coastguard Worker if (relocateTable(dyn, DT_RELA) && relocateTable(dyn, DT_REL)) {
760*84e33947SAndroid Build Coastguard Worker return true;
761*84e33947SAndroid Build Coastguard Worker }
762*84e33947SAndroid Build Coastguard Worker LOGE("Unable to resolve all symbols in the binary");
763*84e33947SAndroid Build Coastguard Worker return false;
764*84e33947SAndroid Build Coastguard Worker }
765*84e33947SAndroid Build Coastguard Worker
callAtexitFunctions()766*84e33947SAndroid Build Coastguard Worker void NanoappLoader::callAtexitFunctions() {
767*84e33947SAndroid Build Coastguard Worker while (!mAtexitFunctions.empty()) {
768*84e33947SAndroid Build Coastguard Worker struct AtExitCallback cb = mAtexitFunctions.back();
769*84e33947SAndroid Build Coastguard Worker if (cb.arg.has_value()) {
770*84e33947SAndroid Build Coastguard Worker LOGV("Calling __cxa_atexit at %p, arg %p", cb.func1, cb.arg.value());
771*84e33947SAndroid Build Coastguard Worker cb.func1(cb.arg.value());
772*84e33947SAndroid Build Coastguard Worker } else {
773*84e33947SAndroid Build Coastguard Worker LOGV("Calling atexit at %p", cb.func0);
774*84e33947SAndroid Build Coastguard Worker cb.func0();
775*84e33947SAndroid Build Coastguard Worker }
776*84e33947SAndroid Build Coastguard Worker mAtexitFunctions.pop_back();
777*84e33947SAndroid Build Coastguard Worker }
778*84e33947SAndroid Build Coastguard Worker }
779*84e33947SAndroid Build Coastguard Worker
callTerminatorArray()780*84e33947SAndroid Build Coastguard Worker void NanoappLoader::callTerminatorArray() {
781*84e33947SAndroid Build Coastguard Worker for (size_t i = 0; i < mNumSectionHeaders; ++i) {
782*84e33947SAndroid Build Coastguard Worker const char *name = getSectionHeaderName(mSectionHeadersPtr[i].sh_name);
783*84e33947SAndroid Build Coastguard Worker if (strncmp(name, kFiniArrayName, strlen(kFiniArrayName)) == 0) {
784*84e33947SAndroid Build Coastguard Worker uintptr_t finiArray =
785*84e33947SAndroid Build Coastguard Worker static_cast<uintptr_t>(mLoadBias + mSectionHeadersPtr[i].sh_addr);
786*84e33947SAndroid Build Coastguard Worker uintptr_t offset = 0;
787*84e33947SAndroid Build Coastguard Worker while (offset < mSectionHeadersPtr[i].sh_size) {
788*84e33947SAndroid Build Coastguard Worker ElfAddr *funcPtr = reinterpret_cast<ElfAddr *>(finiArray + offset);
789*84e33947SAndroid Build Coastguard Worker uintptr_t finiFunction = static_cast<uintptr_t>(*funcPtr);
790*84e33947SAndroid Build Coastguard Worker ((void (*)())finiFunction)();
791*84e33947SAndroid Build Coastguard Worker offset += sizeof(finiFunction);
792*84e33947SAndroid Build Coastguard Worker }
793*84e33947SAndroid Build Coastguard Worker break;
794*84e33947SAndroid Build Coastguard Worker }
795*84e33947SAndroid Build Coastguard Worker }
796*84e33947SAndroid Build Coastguard Worker }
797*84e33947SAndroid Build Coastguard Worker
getTokenDatabaseSectionInfo(uint32_t * offset,size_t * size)798*84e33947SAndroid Build Coastguard Worker void NanoappLoader::getTokenDatabaseSectionInfo(uint32_t *offset,
799*84e33947SAndroid Build Coastguard Worker size_t *size) {
800*84e33947SAndroid Build Coastguard Worker // Find token database.
801*84e33947SAndroid Build Coastguard Worker SectionHeader *pwTokenTableHeader = getSectionHeader(kTokenTableName);
802*84e33947SAndroid Build Coastguard Worker if (pwTokenTableHeader != nullptr) {
803*84e33947SAndroid Build Coastguard Worker if (pwTokenTableHeader->sh_size != 0) {
804*84e33947SAndroid Build Coastguard Worker *size = pwTokenTableHeader->sh_size;
805*84e33947SAndroid Build Coastguard Worker *offset = pwTokenTableHeader->sh_offset;
806*84e33947SAndroid Build Coastguard Worker } else {
807*84e33947SAndroid Build Coastguard Worker LOGE("Found empty token database");
808*84e33947SAndroid Build Coastguard Worker *size = 0;
809*84e33947SAndroid Build Coastguard Worker *offset = 0;
810*84e33947SAndroid Build Coastguard Worker }
811*84e33947SAndroid Build Coastguard Worker } else {
812*84e33947SAndroid Build Coastguard Worker *size = 0;
813*84e33947SAndroid Build Coastguard Worker *offset = 0;
814*84e33947SAndroid Build Coastguard Worker }
815*84e33947SAndroid Build Coastguard Worker }
816*84e33947SAndroid Build Coastguard Worker
817*84e33947SAndroid Build Coastguard Worker } // namespace chre
818