[FEATURE] Implement kernel -> user connection
[platform/core/system/swap-manager.git] / daemon / elf.c
1 /*
2  *  DA manager
3  *
4  * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact:
7  *
8  * Cherepanov Vitaliy <v.cherepanov@samsung.com>
9  * Dmitry Bogatov     <d.bogatov@samsung.com>
10  * Nikita Kalyazin    <n.kalyazin@samsung.com>
11  *
12  * Licensed under the Apache License, Version 2.0 (the "License");
13  * you may not use this file except in compliance with the License.
14  * You may obtain a copy of the License at
15  *
16  * http://www.apache.org/licenses/LICENSE-2.0
17  *
18  * Unless required by applicable law or agreed to in writing, software
19  * distributed under the License is distributed on an "AS IS" BASIS,
20  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21  * See the License for the specific language governing permissions and
22  * limitations under the License.
23  *
24  * Contributors:
25  * - Samsung RnD Institute Russia
26  *
27  */
28
29
30 #include <ctype.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <sys/mman.h>
34 #include <fcntl.h>
35 #include <unistd.h>
36 #include <elf.h>
37 #include <stdbool.h>
38 #include <string.h>
39 #include <stdio.h>
40 #include <errno.h>
41 #include "elf.h"
42
43 #define SIZEOF_VOID_P 4
44 #if SIZEOF_VOID_P == 8
45 typedef Elf64_Ehdr Elf_Ehdr;
46 typedef Elf64_Shdr Elf_Shdr;
47 #elif SIZEOF_VOID_P == 4
48 typedef Elf32_Ehdr Elf_Ehdr;
49 typedef Elf32_Shdr Elf_Shdr;
50 #else
51 #error "Unknown void* size"
52 #endif
53
54 static size_t fsize(int fd)
55 {
56         struct stat buf;
57         fstat(fd, &buf);
58         return buf.st_size;
59 }
60
61 static void *mmap_file(const char *filepath, size_t * len)
62 {
63         int fd = open(filepath, O_RDONLY);
64         if (fd < 0)
65                 return NULL;
66         *len = fsize(fd);
67         void *mem = mmap(NULL, *len, PROT_READ, MAP_PRIVATE, fd, 0);
68         close(fd);
69         return mem == MAP_FAILED ? NULL : mem;
70 }
71
72 static const Elf_Shdr *elf_find_debug_header(const void *obj)
73 {
74         const Elf_Ehdr *elf_header = obj;
75         const Elf_Shdr *section_table = obj + elf_header->e_shoff;
76         const Elf_Shdr *string_entry = section_table + elf_header->e_shstrndx;
77         const char *string_section = obj + string_entry->sh_offset;
78         int index;
79
80         for (index = 0; index != elf_header->e_shnum; ++index) {
81                 const Elf_Shdr *entry = section_table + index;
82                 if (!strcmp(".debug_str", string_section + entry->sh_name))
83                         return entry;
84         }
85         return NULL;
86 }
87
88 static int read_elf_header(Elf_Ehdr * header, const char *filepath)
89 {
90         int fd = open(filepath, O_RDONLY);
91         if (fd < 0)
92                 return -ENOENT;
93         bool read_failed = read(fd, header, sizeof(*header)) != sizeof(*header);
94         close(fd);
95         return read_failed ? -EIO : 0;
96 }
97
98 static int elf_type(const char *filepath)
99 {
100         Elf_Ehdr header;
101         int err = read_elf_header(&header, filepath);
102         return err ? err : header.e_type;
103 }
104
105 uint32_t get_binary_type(const char *path)
106 {
107         int type = elf_type(path);
108
109         switch (type) {
110         case ET_DYN:
111                 return BINARY_TYPE_PIE;
112         case ET_EXEC:
113                 return BINARY_TYPE_NO_PIE;
114         default:
115                 return BINARY_TYPE_UNKNOWN;
116         }
117 }
118
119 static int is_like_absolute_path(const char *str)
120 {
121         if (*str == '/')
122                 return 1;
123         if (isupper(*str) && str[1] == ':' && str[2] == '\\')
124                 return 1;
125         return 0;
126 }
127
128 static bool exist(const char *filename)
129 {
130         struct stat decoy;
131         return stat(filename, &decoy) == 0;
132 }
133
134 static void suffix_filename(char buf[PATH_MAX], const char *filename)
135 {
136         char adj_filename[PATH_MAX];
137         sprintf(adj_filename, "%s.exe", filename);
138         const char *use_filename = exist(adj_filename) ? adj_filename
139                                                        : filename;
140         strcpy(buf, use_filename);
141 }
142
143 void get_build_dir(char builddir[PATH_MAX], const char *filename)
144 {
145         size_t len;
146         void *filemem;
147         char adj_filename[PATH_MAX];
148         suffix_filename(adj_filename, filename);
149
150         filemem = mmap_file(adj_filename, &len);
151         if (filemem) {
152                 const Elf_Shdr *debug_header = elf_find_debug_header(filemem);
153                 if (debug_header) {
154                         const char *debug_section =
155                             filemem + debug_header->sh_offset;
156                         const char *debug_section_end =
157                             debug_section + debug_header->sh_size;
158                         const char *p = debug_section;
159                         /* `is_like_absolute_path' checks three chars forward. */
160                         while (p < debug_section_end - 3) {
161                                 if (is_like_absolute_path(p)) {
162                                         snprintf(builddir, PATH_MAX, "%s", p);
163                                         return;
164                                 }
165                                 p = 1 + memchr(p, '\0', debug_section_end - p);
166                         }
167                 }
168                 munmap(filemem, len);
169         }
170         *builddir = '\0';
171 }