Skip to content

Commit b0bd49f

Browse files
authored
Merge branch 'dev' into dev
2 parents 0dfa357 + f9c5f1a commit b0bd49f

File tree

6 files changed

+272
-19
lines changed

6 files changed

+272
-19
lines changed

examples/rootfs

examples/src/linux/vshttpd.c

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
/*
2+
AUTHOR: Abhijeet Rastogi (http://www.google.com/profiles/abhijeet.1989)
3+
4+
This is a very simple HTTP server. Default port is 10000 and ROOT for the server is your current working directory..
5+
6+
You can provide command line arguments like:- $./a.aout -p [port] -r [path]
7+
8+
for ex.
9+
$./a.out -p 50000 -r /home/
10+
to start a server at port 50000 with root directory as "/home"
11+
12+
$./a.out -r /home/shadyabhi
13+
starts the server at port 10000 with ROOT as /home/shadyabhi
14+
15+
*/
16+
17+
#include<stdio.h>
18+
#include<string.h>
19+
#include<stdlib.h>
20+
#include<unistd.h>
21+
#include<sys/types.h>
22+
#include<sys/stat.h>
23+
#include<sys/socket.h>
24+
#include<arpa/inet.h>
25+
#include<netdb.h>
26+
#include<signal.h>
27+
#include<fcntl.h>
28+
29+
#define CONNMAX 1000
30+
#define BYTES 1024
31+
32+
char *ROOT;
33+
int listenfd, clients[CONNMAX];
34+
void error(char *);
35+
void startServer(char *);
36+
void respond(int);
37+
38+
int main(int argc, char* argv[])
39+
{
40+
struct sockaddr_in clientaddr;
41+
socklen_t addrlen;
42+
char c;
43+
44+
//Default Values PATH = ~/ and PORT=10000
45+
char PORT[6];
46+
ROOT = getenv("PWD");
47+
strcpy(PORT,"10000");
48+
49+
int slot=0;
50+
51+
//Parsing the command line arguments
52+
while ((c = getopt (argc, argv, "p:r:")) != -1)
53+
switch (c)
54+
{
55+
case 'r':
56+
ROOT = malloc(strlen(optarg));
57+
strcpy(ROOT,optarg);
58+
break;
59+
case 'p':
60+
strcpy(PORT,optarg);
61+
break;
62+
case '?':
63+
fprintf(stderr,"Wrong arguments given!!!\n");
64+
exit(1);
65+
default:
66+
exit(1);
67+
}
68+
69+
printf("Server started at port no. %s%s%s with root directory as %s%s%s\n","\033[92m",PORT,"\033[0m","\033[92m",ROOT,"\033[0m");
70+
// Setting all elements to -1: signifies there is no client connected
71+
int i;
72+
for (i=0; i<CONNMAX; i++)
73+
clients[i]=-1;
74+
startServer(PORT);
75+
76+
// ACCEPT connections
77+
while (1)
78+
{
79+
addrlen = sizeof(clientaddr);
80+
clients[slot] = accept (listenfd, (struct sockaddr *) &clientaddr, &addrlen);
81+
82+
if (clients[slot]<0)
83+
error ("accept() error");
84+
else
85+
{
86+
if ( fork()==0 )
87+
{
88+
respond(slot);
89+
exit(0);
90+
}
91+
}
92+
93+
while (clients[slot]!=-1) slot = (slot+1)%CONNMAX;
94+
}
95+
96+
return 0;
97+
}
98+
99+
//start server
100+
void startServer(char *port)
101+
{
102+
struct addrinfo hints, *res, *p;
103+
104+
// getaddrinfo for host
105+
memset (&hints, 0, sizeof(hints));
106+
hints.ai_family = AF_INET;
107+
hints.ai_socktype = SOCK_STREAM;
108+
hints.ai_flags = AI_PASSIVE;
109+
if (getaddrinfo( NULL, port, &hints, &res) != 0)
110+
{
111+
perror ("getaddrinfo() error");
112+
exit(1);
113+
}
114+
// socket and bind
115+
for (p = res; p!=NULL; p=p->ai_next)
116+
{
117+
listenfd = socket (p->ai_family, p->ai_socktype, 0);
118+
if (listenfd == -1) continue;
119+
if (bind(listenfd, p->ai_addr, p->ai_addrlen) == 0) break;
120+
}
121+
if (p==NULL)
122+
{
123+
perror ("socket() or bind()");
124+
exit(1);
125+
}
126+
127+
freeaddrinfo(res);
128+
129+
// listen for incoming connections
130+
if ( listen (listenfd, 1000000) != 0 )
131+
{
132+
perror("listen() error");
133+
exit(1);
134+
}
135+
}
136+
137+
//client connection
138+
void respond(int n)
139+
{
140+
char mesg[99999], *reqline[3], data_to_send[BYTES], path[99999];
141+
int rcvd, fd, bytes_read;
142+
143+
memset( (void*)mesg, (int)'\0', 99999 );
144+
145+
rcvd=recv(clients[n], mesg, 99999, 0);
146+
147+
if (rcvd<0) // receive error
148+
fprintf(stderr,("recv() error\n"));
149+
else if (rcvd==0) // receive socket closed
150+
fprintf(stderr,"Client disconnected upexpectedly.\n");
151+
else // message received
152+
{
153+
printf("%s", mesg);
154+
reqline[0] = strtok (mesg, " \t\n");
155+
if ( strncmp(reqline[0], "GET\0", 4)==0 )
156+
{
157+
reqline[1] = strtok (NULL, " \t");
158+
reqline[2] = strtok (NULL, " \t\n");
159+
if ( strncmp( reqline[2], "HTTP/1.0", 8)!=0 && strncmp( reqline[2], "HTTP/1.1", 8)!=0 )
160+
{
161+
write(clients[n], "HTTP/1.0 400 Bad Request\n", 25);
162+
}
163+
else
164+
{
165+
if ( strncmp(reqline[1], "/\0", 2)==0 )
166+
reqline[1] = "/index.html"; //Because if no file is specified, index.html will be opened by default (like it happens in APACHE...
167+
168+
strcpy(path, ROOT);
169+
strcpy(&path[strlen(ROOT)], reqline[1]);
170+
printf("file: %s\n", path);
171+
172+
if ( (fd=open(path, O_RDONLY))!=-1 ) //FILE FOUND
173+
{
174+
send(clients[n], "HTTP/1.0 200 OK\n\n", 17, 0);
175+
while ( (bytes_read=read(fd, data_to_send, BYTES))>0 )
176+
write (clients[n], data_to_send, bytes_read);
177+
}
178+
else write(clients[n], "HTTP/1.0 404 Not Found\n", 23); //FILE NOT FOUND
179+
}
180+
}
181+
}
182+
183+
//Closing SOCKET
184+
shutdown (clients[n], SHUT_RDWR); //All further send and recieve operations are DISABLED...
185+
close(clients[n]);
186+
clients[n]=-1;
187+
}

qiling/arch/arm.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,24 @@ def enable_vfp(self) -> None:
104104

105105
def check_thumb(self):
106106
return UC_MODE_THUMB if self.__is_thumb() else UC_MODE_ARM
107+
108+
"""
109+
set_tls
110+
"""
111+
def init_get_tls(self):
112+
self.ql.mem.map(0xFFFF0000, 0x1000, info="[arm_tls]")
113+
"""
114+
'adr r0, data; ldr r0, [r0]; mov pc, lr; data:.ascii "\x00\x00"'
115+
"""
116+
sc = b'\x04\x00\x8f\xe2\x00\x00\x90\xe5\x0e\xf0\xa0\xe1\x00\x00\x00\x00'
117+
118+
# if ql.archendian == QL_ENDIAN.EB:
119+
# sc = swap_endianess(sc)
120+
121+
self.ql.mem.write(self.ql.arch.arm_get_tls_addr, sc)
122+
self.ql.log.debug("Set init_kernel_get_tls")
123+
124+
def swap_endianess(self, s: bytes, blksize=4) -> bytes:
125+
blocks = (s[i:i + blksize] for i in range(0, len(s), blksize))
126+
127+
return b''.join(bytes(reversed(b)) for b in blocks)

qiling/os/linux/linux.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
from qiling.os.posix.const import NR_OPEN
1717
from qiling.os.posix.posix import QlOsPosix
1818

19-
from . import utils
2019
from . import futex
2120
from . import thread
2221

@@ -56,7 +55,7 @@ def load(self):
5655
self.ql.arch.enable_vfp()
5756
self.ql.hook_intno(self.hook_syscall, 2)
5857
self.thread_class = thread.QlLinuxARMThread
59-
utils.ql_arm_init_get_tls(self.ql)
58+
self.ql.arch.init_get_tls()
6059

6160
# MIPS32
6261
elif self.ql.archtype == QL_ARCH.MIPS:

qiling/os/qnx/qnx.py

Lines changed: 59 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,46 @@
55

66
from typing import Callable
77
import os
8+
9+
from typing import Callable
810
from unicorn import UcError
911

12+
from qiling import Qiling
1013
from qiling.os.posix.posix import QlOsPosix
1114
from qiling.os.qnx.const import NTO_SIDE_CHANNEL, SYSMGR_PID, SYSMGR_CHID, SYSMGR_COID
1215
from qiling.os.qnx.helpers import QnxConn
1316
from qiling.os.qnx.structs import _thread_local_storage
14-
from qiling.os.fcall import QlFunctionCall
17+
1518
from qiling.cc import QlCC, intel, arm, mips, riscv
1619
from qiling.const import QL_ARCH, QL_INTERCEPT
20+
from qiling.os.fcall import QlFunctionCall
21+
from qiling.os.const import *
22+
from qiling.os.posix.const import NR_OPEN
23+
from qiling.os.posix.posix import QlOsPosix
1724

1825
class QlOsQnx(QlOsPosix):
19-
def __init__(self, ql):
26+
def __init__(self, ql: Qiling):
2027
super(QlOsQnx, self).__init__(ql)
28+
29+
self.ql = ql
30+
31+
cc: QlCC = {
32+
QL_ARCH.X86 : intel.cdecl,
33+
QL_ARCH.X8664 : intel.amd64,
34+
QL_ARCH.ARM : arm.aarch32,
35+
QL_ARCH.ARM64 : arm.aarch64,
36+
QL_ARCH.MIPS : mips.mipso32,
37+
QL_ARCH.RISCV : riscv.riscv,
38+
QL_ARCH.RISCV64: riscv.riscv,
39+
}[ql.archtype](ql)
40+
41+
self.fcall = QlFunctionCall(ql, cc)
42+
43+
self.thread_class = None
44+
self.futexm = None
45+
self.fh = None
46+
self.function_after_load_list = []
47+
self.elf_mem_start = 0x0
2148
self.load()
2249

2350
cc: QlCC = {
@@ -48,11 +75,12 @@ def load(self):
4875
if self.ql.code:
4976
return
5077

51-
if self.ql.archtype!= QL_ARCH.ARM:
52-
return
53-
54-
self.ql.arch.enable_vfp()
55-
self.ql.hook_intno(self.hook_syscall, 2)
78+
# ARM
79+
if self.ql.archtype == QL_ARCH.ARM:
80+
self.ql.arch.enable_vfp()
81+
self.ql.hook_intno(self.hook_syscall, 2)
82+
#self.thread_class = thread.QlLinuxARMThread
83+
self.ql.arch.init_get_tls()
5684

5785

5886
def hook_syscall(self, intno= None, int = None):
@@ -63,7 +91,17 @@ def add_function_hook(self, fn: str, cb: Callable, intercept: QL_INTERCEPT):
6391
self.ql.os.function_hook.add_function_hook(fn, cb, intercept)
6492

6593

66-
def hook_sigtrap(self, intno= None, int = None):
94+
def register_function_after_load(self, function):
95+
if function not in self.function_after_load_list:
96+
self.function_after_load_list.append(function)
97+
98+
99+
def run_function_after_load(self):
100+
for f in self.function_after_load_list:
101+
f()
102+
103+
104+
def hook_sigtrap(self, intno= None, int = None):
67105
self.ql.log.info("Trap Found")
68106
self.emu_error()
69107
exit(1)
@@ -76,15 +114,15 @@ def run(self):
76114
if self.ql.entry_point is not None:
77115
self.ql.loader.elf_entry = self.ql.entry_point
78116

79-
self.cpupage_addr = int(self.ql.os.profile.get("OS32", "cpupage_address"), 16)
80-
self.cpupage_tls_addr = int(self.ql.os.profile.get("OS32", "cpupage_tls_address"), 16)
81-
self.tls_data_addr = int(self.ql.os.profile.get("OS32", "tls_data_address"), 16)
82-
83-
self.syspage_addr = int(self.ql.os.profile.get("OS32", "syspage_address"), 16)
117+
self.cpupage_addr = int(self.ql.os.profile.get("OS32", "cpupage_address"), 16)
118+
self.cpupage_tls_addr = int(self.ql.os.profile.get("OS32", "cpupage_tls_address"), 16)
119+
self.tls_data_addr = int(self.ql.os.profile.get("OS32", "tls_data_address"), 16)
120+
self.syspage_addr = int(self.ql.os.profile.get("OS32", "syspage_address"), 16)
121+
syspage_path = os.path.join(self.ql.rootfs, "syspage.bin")
84122

85123
self.ql.mem.map(self.syspage_addr, 0x4000, info="[syspage_mem]")
86124

87-
syspage_path = os.path.join(self.ql.rootfs, "syspage.bin")
125+
88126
with open(syspage_path, "rb") as sp:
89127
self.ql.mem.write(self.syspage_addr, sp.read())
90128

@@ -108,8 +146,13 @@ def run(self):
108146
self.ql.emu_start(self.entry_point, (self.entry_point + len(self.ql.code)), self.ql.timeout, self.ql.count)
109147
else:
110148
if self.ql.loader.elf_entry != self.ql.loader.entry_point:
111-
self.ql.emu_start(self.ql.loader.entry_point, self.ql.loader.elf_entry, self.ql.timeout)
112-
self.ql.enable_lib_patch()
149+
entry_address = self.ql.loader.elf_entry
150+
if self.ql.archtype == QL_ARCH.ARM and entry_address & 1 == 1:
151+
entry_address -= 1
152+
self.ql.emu_start(self.ql.loader.entry_point, entry_address, self.ql.timeout)
153+
self.run_function_after_load()
154+
self.ql.loader.skip_exit_check = False
155+
self.ql.write_exit_trap()
113156

114157
self.ql.emu_start(self.ql.loader.elf_entry, self.exit_point, self.ql.timeout, self.ql.count)
115158

tests/test_qnx.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,16 +13,19 @@
1313
from qiling.os.const import STRING
1414

1515
class QNXTest(unittest.TestCase):
16+
1617
def test_arm_qnx_static(self):
1718
env = {
1819
"FOO": "bar"
1920
}
2021
ql = Qiling(["../examples/rootfs/arm_qnx/bin/hello_static", "foo", "bar"], "../examples/rootfs/arm_qnx", env=env, verbose=QL_VERBOSE.DEBUG)
2122
ql.run()
2223

24+
2325
def test_arm_qnx_sqrt(self):
2426
ql = Qiling(["../examples/rootfs/arm_qnx/bin/hello_sqrt"], "../examples/rootfs/arm_qnx", verbose=QL_VERBOSE.DEBUG)
2527
ql.run()
28+
2629

2730
def test_set_api_arm_qnx_sqrt(self):
2831
self.set_api_puts_onenter = False

0 commit comments

Comments
 (0)