1*387f9dfdSAndroid Build Coastguard Worker // SPDX-License-Identifier: (LGPL-2.1 OR BSD-2-Clause)
2*387f9dfdSAndroid Build Coastguard Worker /* Copyright (c) 2021 Google LLC. */
3*387f9dfdSAndroid Build Coastguard Worker #ifndef _GNU_SOURCE
4*387f9dfdSAndroid Build Coastguard Worker #define _GNU_SOURCE
5*387f9dfdSAndroid Build Coastguard Worker #endif
6*387f9dfdSAndroid Build Coastguard Worker #include <sys/types.h>
7*387f9dfdSAndroid Build Coastguard Worker #include <sys/stat.h>
8*387f9dfdSAndroid Build Coastguard Worker #include <fcntl.h>
9*387f9dfdSAndroid Build Coastguard Worker #include <stdio.h>
10*387f9dfdSAndroid Build Coastguard Worker #include <stdarg.h>
11*387f9dfdSAndroid Build Coastguard Worker #include <stdlib.h>
12*387f9dfdSAndroid Build Coastguard Worker #include <string.h>
13*387f9dfdSAndroid Build Coastguard Worker #include <unistd.h>
14*387f9dfdSAndroid Build Coastguard Worker #include <errno.h>
15*387f9dfdSAndroid Build Coastguard Worker #include <limits.h>
16*387f9dfdSAndroid Build Coastguard Worker #include <gelf.h>
17*387f9dfdSAndroid Build Coastguard Worker
18*387f9dfdSAndroid Build Coastguard Worker #define warn(...) fprintf(stderr, __VA_ARGS__)
19*387f9dfdSAndroid Build Coastguard Worker
20*387f9dfdSAndroid Build Coastguard Worker /*
21*387f9dfdSAndroid Build Coastguard Worker * Returns 0 on success; -1 on failure. On sucess, returns via `path` the full
22*387f9dfdSAndroid Build Coastguard Worker * path to the program for pid.
23*387f9dfdSAndroid Build Coastguard Worker */
get_pid_binary_path(pid_t pid,char * path,size_t path_sz)24*387f9dfdSAndroid Build Coastguard Worker int get_pid_binary_path(pid_t pid, char *path, size_t path_sz)
25*387f9dfdSAndroid Build Coastguard Worker {
26*387f9dfdSAndroid Build Coastguard Worker ssize_t ret;
27*387f9dfdSAndroid Build Coastguard Worker char proc_pid_exe[32];
28*387f9dfdSAndroid Build Coastguard Worker
29*387f9dfdSAndroid Build Coastguard Worker if (snprintf(proc_pid_exe, sizeof(proc_pid_exe), "/proc/%d/exe", pid)
30*387f9dfdSAndroid Build Coastguard Worker >= sizeof(proc_pid_exe)) {
31*387f9dfdSAndroid Build Coastguard Worker warn("snprintf /proc/PID/exe failed");
32*387f9dfdSAndroid Build Coastguard Worker return -1;
33*387f9dfdSAndroid Build Coastguard Worker }
34*387f9dfdSAndroid Build Coastguard Worker ret = readlink(proc_pid_exe, path, path_sz);
35*387f9dfdSAndroid Build Coastguard Worker if (ret < 0) {
36*387f9dfdSAndroid Build Coastguard Worker warn("No such pid %d\n", pid);
37*387f9dfdSAndroid Build Coastguard Worker return -1;
38*387f9dfdSAndroid Build Coastguard Worker }
39*387f9dfdSAndroid Build Coastguard Worker if (ret >= path_sz) {
40*387f9dfdSAndroid Build Coastguard Worker warn("readlink truncation");
41*387f9dfdSAndroid Build Coastguard Worker return -1;
42*387f9dfdSAndroid Build Coastguard Worker }
43*387f9dfdSAndroid Build Coastguard Worker path[ret] = '\0';
44*387f9dfdSAndroid Build Coastguard Worker
45*387f9dfdSAndroid Build Coastguard Worker return 0;
46*387f9dfdSAndroid Build Coastguard Worker }
47*387f9dfdSAndroid Build Coastguard Worker
48*387f9dfdSAndroid Build Coastguard Worker /*
49*387f9dfdSAndroid Build Coastguard Worker * Returns 0 on success; -1 on failure. On success, returns via `path` the full
50*387f9dfdSAndroid Build Coastguard Worker * path to a library matching the name `lib` that is loaded into pid's address
51*387f9dfdSAndroid Build Coastguard Worker * space.
52*387f9dfdSAndroid Build Coastguard Worker */
get_pid_lib_path(pid_t pid,const char * lib,char * path,size_t path_sz)53*387f9dfdSAndroid Build Coastguard Worker int get_pid_lib_path(pid_t pid, const char *lib, char *path, size_t path_sz)
54*387f9dfdSAndroid Build Coastguard Worker {
55*387f9dfdSAndroid Build Coastguard Worker FILE *maps;
56*387f9dfdSAndroid Build Coastguard Worker char *p;
57*387f9dfdSAndroid Build Coastguard Worker char proc_pid_maps[32];
58*387f9dfdSAndroid Build Coastguard Worker char line_buf[1024];
59*387f9dfdSAndroid Build Coastguard Worker char path_buf[1024];
60*387f9dfdSAndroid Build Coastguard Worker
61*387f9dfdSAndroid Build Coastguard Worker if (snprintf(proc_pid_maps, sizeof(proc_pid_maps), "/proc/%d/maps", pid)
62*387f9dfdSAndroid Build Coastguard Worker >= sizeof(proc_pid_maps)) {
63*387f9dfdSAndroid Build Coastguard Worker warn("snprintf /proc/PID/maps failed");
64*387f9dfdSAndroid Build Coastguard Worker return -1;
65*387f9dfdSAndroid Build Coastguard Worker }
66*387f9dfdSAndroid Build Coastguard Worker maps = fopen(proc_pid_maps, "r");
67*387f9dfdSAndroid Build Coastguard Worker if (!maps) {
68*387f9dfdSAndroid Build Coastguard Worker warn("No such pid %d\n", pid);
69*387f9dfdSAndroid Build Coastguard Worker return -1;
70*387f9dfdSAndroid Build Coastguard Worker }
71*387f9dfdSAndroid Build Coastguard Worker while (fgets(line_buf, sizeof(line_buf), maps)) {
72*387f9dfdSAndroid Build Coastguard Worker if (sscanf(line_buf, "%*x-%*x %*s %*x %*s %*u %s", path_buf) != 1)
73*387f9dfdSAndroid Build Coastguard Worker continue;
74*387f9dfdSAndroid Build Coastguard Worker /* e.g. /usr/lib/x86_64-linux-gnu/libc-2.31.so */
75*387f9dfdSAndroid Build Coastguard Worker p = strrchr(path_buf, '/');
76*387f9dfdSAndroid Build Coastguard Worker if (!p)
77*387f9dfdSAndroid Build Coastguard Worker continue;
78*387f9dfdSAndroid Build Coastguard Worker if (strncmp(p, "/lib", 4))
79*387f9dfdSAndroid Build Coastguard Worker continue;
80*387f9dfdSAndroid Build Coastguard Worker p += 4;
81*387f9dfdSAndroid Build Coastguard Worker if (strncmp(lib, p, strlen(lib)))
82*387f9dfdSAndroid Build Coastguard Worker continue;
83*387f9dfdSAndroid Build Coastguard Worker p += strlen(lib);
84*387f9dfdSAndroid Build Coastguard Worker /* libraries can have - or . after the name */
85*387f9dfdSAndroid Build Coastguard Worker if (*p != '.' && *p != '-')
86*387f9dfdSAndroid Build Coastguard Worker continue;
87*387f9dfdSAndroid Build Coastguard Worker if (strnlen(path_buf, 1024) >= path_sz) {
88*387f9dfdSAndroid Build Coastguard Worker warn("path size too small\n");
89*387f9dfdSAndroid Build Coastguard Worker return -1;
90*387f9dfdSAndroid Build Coastguard Worker }
91*387f9dfdSAndroid Build Coastguard Worker strcpy(path, path_buf);
92*387f9dfdSAndroid Build Coastguard Worker fclose(maps);
93*387f9dfdSAndroid Build Coastguard Worker return 0;
94*387f9dfdSAndroid Build Coastguard Worker }
95*387f9dfdSAndroid Build Coastguard Worker
96*387f9dfdSAndroid Build Coastguard Worker warn("Cannot find library %s\n", lib);
97*387f9dfdSAndroid Build Coastguard Worker fclose(maps);
98*387f9dfdSAndroid Build Coastguard Worker return -1;
99*387f9dfdSAndroid Build Coastguard Worker }
100*387f9dfdSAndroid Build Coastguard Worker
101*387f9dfdSAndroid Build Coastguard Worker /*
102*387f9dfdSAndroid Build Coastguard Worker * Returns 0 on success; -1 on failure. On success, returns via `path` the full
103*387f9dfdSAndroid Build Coastguard Worker * path to the program.
104*387f9dfdSAndroid Build Coastguard Worker */
which_program(const char * prog,char * path,size_t path_sz)105*387f9dfdSAndroid Build Coastguard Worker static int which_program(const char *prog, char *path, size_t path_sz)
106*387f9dfdSAndroid Build Coastguard Worker {
107*387f9dfdSAndroid Build Coastguard Worker FILE *which;
108*387f9dfdSAndroid Build Coastguard Worker char cmd[100];
109*387f9dfdSAndroid Build Coastguard Worker
110*387f9dfdSAndroid Build Coastguard Worker if (snprintf(cmd, sizeof(cmd), "which %s", prog) >= sizeof(cmd)) {
111*387f9dfdSAndroid Build Coastguard Worker warn("snprintf which prog failed");
112*387f9dfdSAndroid Build Coastguard Worker return -1;
113*387f9dfdSAndroid Build Coastguard Worker }
114*387f9dfdSAndroid Build Coastguard Worker which = popen(cmd, "r");
115*387f9dfdSAndroid Build Coastguard Worker if (!which) {
116*387f9dfdSAndroid Build Coastguard Worker warn("which failed");
117*387f9dfdSAndroid Build Coastguard Worker return -1;
118*387f9dfdSAndroid Build Coastguard Worker }
119*387f9dfdSAndroid Build Coastguard Worker if (!fgets(path, path_sz, which)) {
120*387f9dfdSAndroid Build Coastguard Worker warn("fgets which failed");
121*387f9dfdSAndroid Build Coastguard Worker pclose(which);
122*387f9dfdSAndroid Build Coastguard Worker return -1;
123*387f9dfdSAndroid Build Coastguard Worker }
124*387f9dfdSAndroid Build Coastguard Worker /* which has a \n at the end of the string */
125*387f9dfdSAndroid Build Coastguard Worker path[strlen(path) - 1] = '\0';
126*387f9dfdSAndroid Build Coastguard Worker pclose(which);
127*387f9dfdSAndroid Build Coastguard Worker return 0;
128*387f9dfdSAndroid Build Coastguard Worker }
129*387f9dfdSAndroid Build Coastguard Worker
130*387f9dfdSAndroid Build Coastguard Worker /*
131*387f9dfdSAndroid Build Coastguard Worker * Returns 0 on success; -1 on failure. On success, returns via `path` the full
132*387f9dfdSAndroid Build Coastguard Worker * path to the binary for the given pid.
133*387f9dfdSAndroid Build Coastguard Worker * 1) pid == x, binary == "" : returns the path to x's program
134*387f9dfdSAndroid Build Coastguard Worker * 2) pid == x, binary == "foo" : returns the path to libfoo linked in x
135*387f9dfdSAndroid Build Coastguard Worker * 3) pid == 0, binary == "" : failure: need a pid or a binary
136*387f9dfdSAndroid Build Coastguard Worker * 4) pid == 0, binary == "bar" : returns the path to `which bar`
137*387f9dfdSAndroid Build Coastguard Worker *
138*387f9dfdSAndroid Build Coastguard Worker * For case 4), ideally we'd like to search for libbar too, but we don't support
139*387f9dfdSAndroid Build Coastguard Worker * that yet.
140*387f9dfdSAndroid Build Coastguard Worker */
resolve_binary_path(const char * binary,pid_t pid,char * path,size_t path_sz)141*387f9dfdSAndroid Build Coastguard Worker int resolve_binary_path(const char *binary, pid_t pid, char *path, size_t path_sz)
142*387f9dfdSAndroid Build Coastguard Worker {
143*387f9dfdSAndroid Build Coastguard Worker if (!strcmp(binary, "")) {
144*387f9dfdSAndroid Build Coastguard Worker if (!pid) {
145*387f9dfdSAndroid Build Coastguard Worker warn("Uprobes need a pid or a binary\n");
146*387f9dfdSAndroid Build Coastguard Worker return -1;
147*387f9dfdSAndroid Build Coastguard Worker }
148*387f9dfdSAndroid Build Coastguard Worker return get_pid_binary_path(pid, path, path_sz);
149*387f9dfdSAndroid Build Coastguard Worker }
150*387f9dfdSAndroid Build Coastguard Worker if (pid)
151*387f9dfdSAndroid Build Coastguard Worker return get_pid_lib_path(pid, binary, path, path_sz);
152*387f9dfdSAndroid Build Coastguard Worker
153*387f9dfdSAndroid Build Coastguard Worker if (which_program(binary, path, path_sz)) {
154*387f9dfdSAndroid Build Coastguard Worker /*
155*387f9dfdSAndroid Build Coastguard Worker * If the user is tracing a program by name, we can find it.
156*387f9dfdSAndroid Build Coastguard Worker * But we can't find a library by name yet. We'd need to parse
157*387f9dfdSAndroid Build Coastguard Worker * ld.so.cache or something similar.
158*387f9dfdSAndroid Build Coastguard Worker */
159*387f9dfdSAndroid Build Coastguard Worker warn("Can't find %s (Need a PID if this is a library)\n", binary);
160*387f9dfdSAndroid Build Coastguard Worker return -1;
161*387f9dfdSAndroid Build Coastguard Worker }
162*387f9dfdSAndroid Build Coastguard Worker return 0;
163*387f9dfdSAndroid Build Coastguard Worker }
164*387f9dfdSAndroid Build Coastguard Worker
165*387f9dfdSAndroid Build Coastguard Worker /*
166*387f9dfdSAndroid Build Coastguard Worker * Opens an elf at `path` of kind ELF_K_ELF. Returns NULL on failure. On
167*387f9dfdSAndroid Build Coastguard Worker * success, close with close_elf(e, fd_close).
168*387f9dfdSAndroid Build Coastguard Worker */
open_elf(const char * path,int * fd_close)169*387f9dfdSAndroid Build Coastguard Worker Elf *open_elf(const char *path, int *fd_close)
170*387f9dfdSAndroid Build Coastguard Worker {
171*387f9dfdSAndroid Build Coastguard Worker int fd;
172*387f9dfdSAndroid Build Coastguard Worker Elf *e;
173*387f9dfdSAndroid Build Coastguard Worker
174*387f9dfdSAndroid Build Coastguard Worker if (elf_version(EV_CURRENT) == EV_NONE) {
175*387f9dfdSAndroid Build Coastguard Worker warn("elf init failed\n");
176*387f9dfdSAndroid Build Coastguard Worker return NULL;
177*387f9dfdSAndroid Build Coastguard Worker }
178*387f9dfdSAndroid Build Coastguard Worker fd = open(path, O_RDONLY);
179*387f9dfdSAndroid Build Coastguard Worker if (fd < 0) {
180*387f9dfdSAndroid Build Coastguard Worker warn("Could not open %s\n", path);
181*387f9dfdSAndroid Build Coastguard Worker return NULL;
182*387f9dfdSAndroid Build Coastguard Worker }
183*387f9dfdSAndroid Build Coastguard Worker e = elf_begin(fd, ELF_C_READ, NULL);
184*387f9dfdSAndroid Build Coastguard Worker if (!e) {
185*387f9dfdSAndroid Build Coastguard Worker warn("elf_begin failed: %s\n", elf_errmsg(-1));
186*387f9dfdSAndroid Build Coastguard Worker close(fd);
187*387f9dfdSAndroid Build Coastguard Worker return NULL;
188*387f9dfdSAndroid Build Coastguard Worker }
189*387f9dfdSAndroid Build Coastguard Worker if (elf_kind(e) != ELF_K_ELF) {
190*387f9dfdSAndroid Build Coastguard Worker warn("elf kind %d is not ELF_K_ELF\n", elf_kind(e));
191*387f9dfdSAndroid Build Coastguard Worker elf_end(e);
192*387f9dfdSAndroid Build Coastguard Worker close(fd);
193*387f9dfdSAndroid Build Coastguard Worker return NULL;
194*387f9dfdSAndroid Build Coastguard Worker }
195*387f9dfdSAndroid Build Coastguard Worker *fd_close = fd;
196*387f9dfdSAndroid Build Coastguard Worker return e;
197*387f9dfdSAndroid Build Coastguard Worker }
198*387f9dfdSAndroid Build Coastguard Worker
open_elf_by_fd(int fd)199*387f9dfdSAndroid Build Coastguard Worker Elf *open_elf_by_fd(int fd)
200*387f9dfdSAndroid Build Coastguard Worker {
201*387f9dfdSAndroid Build Coastguard Worker Elf *e;
202*387f9dfdSAndroid Build Coastguard Worker
203*387f9dfdSAndroid Build Coastguard Worker if (elf_version(EV_CURRENT) == EV_NONE) {
204*387f9dfdSAndroid Build Coastguard Worker warn("elf init failed\n");
205*387f9dfdSAndroid Build Coastguard Worker return NULL;
206*387f9dfdSAndroid Build Coastguard Worker }
207*387f9dfdSAndroid Build Coastguard Worker e = elf_begin(fd, ELF_C_READ, NULL);
208*387f9dfdSAndroid Build Coastguard Worker if (!e) {
209*387f9dfdSAndroid Build Coastguard Worker warn("elf_begin failed: %s\n", elf_errmsg(-1));
210*387f9dfdSAndroid Build Coastguard Worker close(fd);
211*387f9dfdSAndroid Build Coastguard Worker return NULL;
212*387f9dfdSAndroid Build Coastguard Worker }
213*387f9dfdSAndroid Build Coastguard Worker if (elf_kind(e) != ELF_K_ELF) {
214*387f9dfdSAndroid Build Coastguard Worker warn("elf kind %d is not ELF_K_ELF\n", elf_kind(e));
215*387f9dfdSAndroid Build Coastguard Worker elf_end(e);
216*387f9dfdSAndroid Build Coastguard Worker close(fd);
217*387f9dfdSAndroid Build Coastguard Worker return NULL;
218*387f9dfdSAndroid Build Coastguard Worker }
219*387f9dfdSAndroid Build Coastguard Worker return e;
220*387f9dfdSAndroid Build Coastguard Worker }
221*387f9dfdSAndroid Build Coastguard Worker
close_elf(Elf * e,int fd_close)222*387f9dfdSAndroid Build Coastguard Worker void close_elf(Elf *e, int fd_close)
223*387f9dfdSAndroid Build Coastguard Worker {
224*387f9dfdSAndroid Build Coastguard Worker elf_end(e);
225*387f9dfdSAndroid Build Coastguard Worker close(fd_close);
226*387f9dfdSAndroid Build Coastguard Worker }
227*387f9dfdSAndroid Build Coastguard Worker
228*387f9dfdSAndroid Build Coastguard Worker /* Returns the offset of a function in the elf file `path`, or -1 on failure. */
get_elf_func_offset(const char * path,const char * func)229*387f9dfdSAndroid Build Coastguard Worker off_t get_elf_func_offset(const char *path, const char *func)
230*387f9dfdSAndroid Build Coastguard Worker {
231*387f9dfdSAndroid Build Coastguard Worker off_t ret = -1;
232*387f9dfdSAndroid Build Coastguard Worker int i, fd = -1;
233*387f9dfdSAndroid Build Coastguard Worker Elf *e;
234*387f9dfdSAndroid Build Coastguard Worker Elf_Scn *scn;
235*387f9dfdSAndroid Build Coastguard Worker Elf_Data *data;
236*387f9dfdSAndroid Build Coastguard Worker GElf_Ehdr ehdr;
237*387f9dfdSAndroid Build Coastguard Worker GElf_Shdr shdr[1];
238*387f9dfdSAndroid Build Coastguard Worker GElf_Phdr phdr;
239*387f9dfdSAndroid Build Coastguard Worker GElf_Sym sym[1];
240*387f9dfdSAndroid Build Coastguard Worker size_t shstrndx, nhdrs;
241*387f9dfdSAndroid Build Coastguard Worker char *n;
242*387f9dfdSAndroid Build Coastguard Worker
243*387f9dfdSAndroid Build Coastguard Worker e = open_elf(path, &fd);
244*387f9dfdSAndroid Build Coastguard Worker
245*387f9dfdSAndroid Build Coastguard Worker if (!gelf_getehdr(e, &ehdr))
246*387f9dfdSAndroid Build Coastguard Worker goto out;
247*387f9dfdSAndroid Build Coastguard Worker
248*387f9dfdSAndroid Build Coastguard Worker if (elf_getshdrstrndx(e, &shstrndx) != 0)
249*387f9dfdSAndroid Build Coastguard Worker goto out;
250*387f9dfdSAndroid Build Coastguard Worker
251*387f9dfdSAndroid Build Coastguard Worker scn = NULL;
252*387f9dfdSAndroid Build Coastguard Worker while ((scn = elf_nextscn(e, scn))) {
253*387f9dfdSAndroid Build Coastguard Worker if (!gelf_getshdr(scn, shdr))
254*387f9dfdSAndroid Build Coastguard Worker continue;
255*387f9dfdSAndroid Build Coastguard Worker if (!(shdr->sh_type == SHT_SYMTAB || shdr->sh_type == SHT_DYNSYM))
256*387f9dfdSAndroid Build Coastguard Worker continue;
257*387f9dfdSAndroid Build Coastguard Worker data = NULL;
258*387f9dfdSAndroid Build Coastguard Worker while ((data = elf_getdata(scn, data))) {
259*387f9dfdSAndroid Build Coastguard Worker for (i = 0; gelf_getsym(data, i, sym); i++) {
260*387f9dfdSAndroid Build Coastguard Worker n = elf_strptr(e, shdr->sh_link, sym->st_name);
261*387f9dfdSAndroid Build Coastguard Worker if (!n)
262*387f9dfdSAndroid Build Coastguard Worker continue;
263*387f9dfdSAndroid Build Coastguard Worker if (GELF_ST_TYPE(sym->st_info) != STT_FUNC)
264*387f9dfdSAndroid Build Coastguard Worker continue;
265*387f9dfdSAndroid Build Coastguard Worker if (!strcmp(n, func)) {
266*387f9dfdSAndroid Build Coastguard Worker ret = sym->st_value;
267*387f9dfdSAndroid Build Coastguard Worker goto check;
268*387f9dfdSAndroid Build Coastguard Worker }
269*387f9dfdSAndroid Build Coastguard Worker }
270*387f9dfdSAndroid Build Coastguard Worker }
271*387f9dfdSAndroid Build Coastguard Worker }
272*387f9dfdSAndroid Build Coastguard Worker
273*387f9dfdSAndroid Build Coastguard Worker check:
274*387f9dfdSAndroid Build Coastguard Worker if (ehdr.e_type == ET_EXEC || ehdr.e_type == ET_DYN) {
275*387f9dfdSAndroid Build Coastguard Worker if (elf_getphdrnum(e, &nhdrs) != 0) {
276*387f9dfdSAndroid Build Coastguard Worker ret = -1;
277*387f9dfdSAndroid Build Coastguard Worker goto out;
278*387f9dfdSAndroid Build Coastguard Worker }
279*387f9dfdSAndroid Build Coastguard Worker for (i = 0; i < (int)nhdrs; i++) {
280*387f9dfdSAndroid Build Coastguard Worker if (!gelf_getphdr(e, i, &phdr))
281*387f9dfdSAndroid Build Coastguard Worker continue;
282*387f9dfdSAndroid Build Coastguard Worker if (phdr.p_type != PT_LOAD || !(phdr.p_flags & PF_X))
283*387f9dfdSAndroid Build Coastguard Worker continue;
284*387f9dfdSAndroid Build Coastguard Worker if (phdr.p_vaddr <= ret && ret < (phdr.p_vaddr + phdr.p_memsz)) {
285*387f9dfdSAndroid Build Coastguard Worker ret = ret - phdr.p_vaddr + phdr.p_offset;
286*387f9dfdSAndroid Build Coastguard Worker goto out;
287*387f9dfdSAndroid Build Coastguard Worker }
288*387f9dfdSAndroid Build Coastguard Worker }
289*387f9dfdSAndroid Build Coastguard Worker ret = -1;
290*387f9dfdSAndroid Build Coastguard Worker }
291*387f9dfdSAndroid Build Coastguard Worker out:
292*387f9dfdSAndroid Build Coastguard Worker close_elf(e, fd);
293*387f9dfdSAndroid Build Coastguard Worker return ret;
294*387f9dfdSAndroid Build Coastguard Worker }
295