MIUISupermarket移植

VerifyError

1
java.lang.VerifyError: Verifier rejected class com.xiaomi.market.util.UIUtils: void com.xiaomi.market.util.UIUtils.setStatusBarDarkMode(android.app.Activity, boolean) failed to verify: void com.xiaomi.market.util.UIUtils.setStatusBarDarkMode(android.app.Activity, boolean): [0x15] type Undefined unexpected as arg to if-eqz/if-nez (declaration of 'com.xiaomi.market.util.UIUtils' appears in /data/app/~~pH0reBrzyfvMag1T-TAoDw==/com.xiaomi.market-EzZXS_MznmhQs5NCCbvqfA==/base.apk!classes2.dex)
  • 一般出现VerifyError都是因为对smali代码修改,导致无法通过验证。当前遇到过的情况有:
    • 插入代码时无意覆盖了下面会用到的寄存器的值,导致寄存器类型不匹配等问题。
    • 对方法参数类型修改但未修改调用时传入的参数
    • 传递参数时传递了类型不匹配的参数

ClassNotFound

在xiaomi商店中使用了Lmiui/os/Build类,该类继承Landroid/os/Build,且存在于小米系统中,导致类找不到。导致运行时闪退。

对于这类小米系统中才能获取到的类,采用等价替换的方法进行修复。如在Lmiui/os/Build中有:

阅读更多

c语言函数绘图

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
#define _XOPEN_SOURCE 500
#define _C99_SOURCE
#include <stdio.h>
#include <math.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <float.h>
//#define LOG_LEVEL DEBUG_LOG
#define DEBUG_LOG 7
#define INFO_LOG 5
#define ERR_LOG 4
#ifndef LOG_LEVEL
#define LOG_LEVEL INFO_LOG
#endif
#ifndef GREATER_CHAR
#define GREATER_CHAR ' '
#endif
#ifndef SMALLER_CHAR
#define SMALLER_CHAR '+'
#endif
void logger(int level, const char *format, ...) {
if(level > LOG_LEVEL) return;
va_list args;
va_start(args, format);
int len = vsnprintf(NULL, 0, format, args)+1;
va_end(args);
va_start(args, format);
char *str = malloc(len);
vsprintf(str, format, args);
va_end(args);
fprintf(stderr, "%s\n", str);
free(str);
}
double x1, x2, _y1, _y2, s1, s2;

#define PUSH(s, n) (s[s##_ptr++] = (n))
#define POP(s, n) (n = s[--s##_ptr])
#define TOP(s, n) (n = s[s##_ptr-1])
#define EMPTY(s) (s##_ptr == 0)
enum {
op_acos = 48,
op_asin ,
op_atan ,
op_cos ,
op_cosh ,
op_sin ,
op_sinh ,
op_tan ,
op_tanh ,
op_exp ,
op_log ,
op_floor ,
op_sqrt ,
op_fabs ,
op_ceil
};
const static int op_min = op_acos;
const static int op_max = op_ceil;

static double stack[1024];
static char op_stack[1024];
static int priv[128] = {
[0 ... 39] = 0,
['('] = 1,
[')'] = 2,
['*'] = 3,
['+'] = 2,
[44] = 0,
['-'] = 2,
[46] = 0,
['/'] = 3,
[48 ... 93] = 0,
['^'] = 4,
[95 ... 127] = 0
};
static int stack_ptr = 0;
static int op_stack_ptr = 0;
void logStack() {
logger(DEBUG_LOG, "op_stack: ");
for(int cnt = 0; cnt < op_stack_ptr; cnt++) {
logger(DEBUG_LOG, "%c ", op_stack[cnt]);
}
logger(DEBUG_LOG, "stack: ");
for(int cnt = 0; cnt < stack_ptr; cnt++) {
logger(DEBUG_LOG, "%lf ", stack[cnt]);
}
logger(DEBUG_LOG, "");
}
void biCheck() {
if(EMPTY(stack)) {
logger(ERR_LOG, "empty stack!");
exit(1);
}
}
void pushOP(char cur_op) {
double n1, n2;
char op;
while(!EMPTY(op_stack) && priv[TOP(op_stack, op)] >= priv[cur_op]) {
POP(op_stack, op);
double res = 0;
POP(stack, n2);
if(!EMPTY(stack))POP(stack, n1);
else n1 = 0;
switch(op) {
case '+':
res = n1 + n2;
break;
case '-':
res = n1 - n2;
break;
case '*':
res = n1 * n2;
break;
case '/':
if(n2 == 0) {
logger(ERR_LOG, "divisor is zeor!");
// exit(1);
}
res = n1 / n2;
break;
case '^':
res = pow(n1, n2);
break;
default:
break;
}
PUSH(stack, res);
}
}
int len_strncmp(const char *a, const char *b) {
return strncmp(a, b, strlen(b));
}
double eval(double y, double x, const char *expr) {
int len = strlen(expr);
int i = 0;
stack_ptr = 0;
op_stack_ptr = 0;
while(i < len) {
switch(expr[i]) {
case '^':
biCheck();
pushOP(expr[i]);
// if(EMPTY(stack)) PUSH(stack, 0);
PUSH(op_stack, expr[i]);
break;
case 'x': case 'X':
PUSH(stack, x);
break;
case 'y': case 'Y':
PUSH(stack, y);
break;
case '(':
PUSH(op_stack, '(');
break;
case ')': {
double n1, n2;
char op;
if(EMPTY(op_stack)) {
logger(ERR_LOG, "no match ')'");
exit(1);
}
pushOP(')');
POP(op_stack, op);
if(TOP(op_stack, op) >= op_min && TOP(op_stack, op) <= op_max) {
POP(op_stack, op);
double n;
if(!EMPTY(stack)) {
POP(stack, n);
} else {
logger(ERR_LOG, "Error : no opvalue");
exit(1);
}
double (*op_func)(double);
switch(op) {
case op_acos:
if(n > 1 || n < -1) return DBL_MAX;
op_func = acos;
break;
case op_asin:
if(n > 1 || n < -1) return DBL_MAX;
op_func = asin;
break;
case op_atan:
op_func = atan;
break;
case op_cos:
op_func = cos;
break;
case op_cosh:
op_func = cosh;
break;
case op_sin:
op_func = sin;
break;
case op_sinh:
op_func = sinh;
break;
case op_tan:
op_func = tan;
break;
case op_tanh:
op_func = tanh;
break;
case op_exp:
op_func = exp;
break;
case op_log:
if(n < 0) return DBL_MAX;
op_func = log;
break;
case op_sqrt:
if(n < 0) return DBL_MAX;
op_func = sqrt;
break;
case op_fabs:
op_func = fabs;
break;
case op_ceil:
op_func = ceil;
break;
case op_floor:
op_func = floor;
break;
}
PUSH(stack, op_func(n));
}
}
break;
case '+':case '-': {
if((i > 0 && expr[i-1] != '(')) { // fix: a-(-b)
// if stack is empty or last op is '(', ‘-’ is an Unary operator
// else it's a Binary operator
biCheck();
pushOP(expr[i]);
} else {
PUSH(stack, 0);
}
PUSH(op_stack, expr[i]);
}
break;
case '*':
case '/':
biCheck();
pushOP(expr[i]);
// if(EMPTY(stack)) PUSH(stack, 0);
PUSH(op_stack, expr[i]);
break;
case 'p': // p1 = 3.14
if(i + 1 < len && expr[i + 1] == 'i') {
PUSH(stack, M_PI);
i++;
} else {
logger(ERR_LOG, "Error 'pi': unknown char(%c)", expr[i]);
exit(1);
}
break;
case 'e': // e = 2.7
PUSH(stack, M_E);
break;
case '0':case '1':case '2':case '3':case '4':case '5':case '6':case '7':case '8':case '9':case '.':
{
double n = 0;
double n1 = 1;
while(i < len) {
if(expr[i] < '0' || expr[i] > '9') {
break;
}
n *= 10;
n += expr[i] - '0';
i++;
}
if(expr[i] == '.') {
i++;
while(i < len && expr[i] != '.') {
if(expr[i] < '0' || expr[i] > '9') {
break;
}
n1 /= 10.0;
n += n1 * (expr[i] - '0');
i++;
}
}if(expr[i] == '.') {
logger(ERR_LOG, "error : two '.' in one number");
exit(1);
}
PUSH(stack, n);
i--;
}
break;
default:
if(!len_strncmp(expr + i, "ACOS")) {
PUSH(op_stack, op_acos);
i+=3;
} else if(!len_strncmp(expr + i, "ASIN")) {
PUSH(op_stack, op_asin);
i+=3;
} else if(!len_strncmp(expr + i, "ATAN")) {
PUSH(op_stack, op_atan);
i+=3;
} else if(!len_strncmp(expr + i, "COS")) {
if(expr[i+3] == 'H') {
PUSH(op_stack, op_cosh);
i+=3;
} else {
PUSH(op_stack, op_cos);
i+=2;
}
} else if(!len_strncmp(expr + i, "SIN")) {
if(expr[i+3] == 'H') {
PUSH(op_stack, op_sinh);
i+=3;
} else {
PUSH(op_stack, op_sin);
i+=2;
}
} else if(!len_strncmp(expr + i, "TAN")) {
if(expr[i+3] == 'H') {
PUSH(op_stack, op_tanh);
i+=3;
} else {
PUSH(op_stack, op_tan);
i+=2;
}
} else if(!len_strncmp(expr + i, "EXP")) {
PUSH(op_stack, op_exp);
i+=2;
} else if(!len_strncmp(expr + i, "LOG")) {
PUSH(op_stack, op_log);
i+=2;
} else if(!len_strncmp(expr + i, "SQRT")) {
PUSH(op_stack, op_sqrt);
i+=3;
} else if(!len_strncmp(expr + i, "FABS")) {
PUSH(op_stack, op_fabs);
i+=3;
} else if(!len_strncmp(expr + i, "CEIL")) {
PUSH(op_stack, op_ceil);
i+=3;
} else if(!len_strncmp(expr + i, "FLOOR")) {
PUSH(op_stack, op_floor);
i+=4;
} else {
logger(ERR_LOG, "Error: unknown char(%c)", expr[i]);
exit(1);
}
break;
}
i++;
logStack();
}
biCheck();
pushOP(0);
logStack();
return stack[0];
}
void INIT(char **argv) {
int i = 0;
_y1 = eval(0, 0, argv[i++]);
_y2 = eval(0, 0, argv[i++]);
s1 = eval(0, 0, argv[i++]);
x1 = eval(0, 0, argv[i++]);
x2 = eval(0, 0, argv[i++]);
s2 = eval(0, 0, argv[i++]);
logger(DEBUG_LOG, "%lf, %lf, %lf, %lf, %lf, %lf\n", _y1, _y2, s1, x1, x2, s2);

}
int main(int argc, char **argv) {
if(argc < 8) {
logger(INFO_LOG, "Usage: %s y1 y2 sy x1 x2 sy expression", argv[0]);
logger(INFO_LOG, "example: %s -1 1 0.125 -1 1 0.0625 \"x*x+y*y-1\" 2>errs.log", argv[0]);
logger(INFO_LOG, "example: %s \"-pi/2\" \"pi/2\" 0.25 \"-3*pi\" \"2*pi\" 0.125 \"y^2-SIN(x+y)^2\" 2>errs.log", argv[0]);
logger(INFO_LOG, "example: %s \"-pi/2\" \"pi/2\" 0.25 \"-3*pi\" \"2*pi\" 0.125 \"y^2-SIN(x)^2\" 2>errs.log", argv[0]);
logger(INFO_LOG, "example: %s \"-2\" \"ACOS(1/2)-pi/4\" 0.125 \"-pi/2\" \"pi/2\" 0.0625 \"y*y+x*x+y-SQRT(y*y+x*x)\" 2>errs.log", argv[0]);
logger(INFO_LOG, "example: %s \"-pi\" \"1\" 0.125 \"-2\" \"2\" 0.0625 \"(ACOS(1-FABS(x))-pi)-y\" \"y-SQRT(1-(FABS(x)-1)^2)\" 2>errs.log", argv[0]);
logger(INFO_LOG, "example: %s \"-1\" \"pi/2\" 0.125 \"-1\" \"1\" 0.0625 \"x*x+(y-FABS(x)^(2.0/3.0))^2-1\" 2>errs.log", argv[0]);

exit(0);
}
INIT(argv + 1);
for(double i = _y2; i >= _y1; ) {
for(double j = x1; j <= x2; ) {
logger(DEBUG_LOG, "x = %lf, y = %lf", j, i);
bool ok = true;
for(char **expr = argv + 7; *expr; expr++) {
if(eval(i, j, *expr) >= 0) {
ok = false;
break;
}
}
if(ok) {
printf("%c", SMALLER_CHAR);
} else {
printf("%c", GREATER_CHAR);
}
j+=s2;
}
printf("\n");
i-=s1;
}
}

example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
.................................
.........+++++++++++++++.........
......+++++++++++++++++++++......
....+++++++++++++++++++++++++....
...+++++++++++++++++++++++++++...
..+++++++++++++++++++++++++++++..
.+++++++++++++++++++++++++++++++.
.+++++++++++++++++++++++++++++++.
.+++++++++++++++++++++++++++++++.
.+++++++++++++++++++++++++++++++.
.+++++++++++++++++++++++++++++++.
..+++++++++++++++++++++++++++++..
...+++++++++++++++++++++++++++...
....+++++++++++++++++++++++++....
......+++++++++++++++++++++......
.........+++++++++++++++.........
.................................
阅读更多

shell编程相关

kill僵尸进程

  • 强制kill掉其父进程,但是会导致shell也死掉
1
ps -ef | grep defunct | awk '{ len=split($0, a, " ");print a[3]; }' | xargs kill -9

geth搭建私链

主要工作

参考go-ethereum官网的Private Networks文档搭建了一个私有链,并总结出几个脚本,可以半自动化地实现geth网络的搭建,脚本已上传至github仓库DLCCB

setup.sh

  • 这一步使用了以下几个工具
    • geth命令,用于生成初始两个节点的账户,使用创世块配置文件对两个账户进行初始化
    • puppeth 用于生成创世块的配置文件,这个命令是交互式的,编写了一个puppeth.txt作为其输入,默认生成一个基于pow的区块链
    • bootnode 用于生成启动bootnode
  • 这一步使用了以下几个linux命令
    • sed 非交互式的文本编辑器,用于读取生成的账户的区块链地址,写入puppeth.txt中,使得puppeth工具能为初始的两个节点分配一定的以太币
    • awk,用于对文本的处理
setup.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
mkdir node1 node2
geth --datadir node1 account new < password.txt
geth --datadir node2 account new < password.txt

sed -i "5i$(cat node1/keystore/UTC--* | awk '{split($0, arr, "\""); print arr[4]}')" puppeth.txt
sed -i "5i$(cat node2/keystore/UTC--* | awk '{split($0, arr, "\""); print arr[4]}')" puppeth.txt
puppeth < puppeth.txt
sed -i "5d" puppeth.txt
sed -i "5d" puppeth.txt

geth init --datadir node1 tianer.json
geth init --datadir node2 tianer.json

cat password.txt | head -n 1 | tee node1/password.txt
cat password.txt | head -n 1 | tee node2/password.txt

bootnode -genkey boot.key
bootnode -nodekey boot.key -addr :30305

两个输入文件的内容

阅读更多