深入理解计算机系统(第三版)/ CSAPP 杂谈,第1章:计算机系统漫游

Published / by sickworm / Leave a Comment

本书第1章向我们介绍了信息的定义,以及程序是如何运行在计算机上的。

信息就是位+上下文

信息的本体是一连串的0101010101的bits,但是bits可以被解析为不同的含义,如何被解析就取决于上下文。

举个生活中的例子。“你好烦啊”如果是在一对情侣的温馨时刻中出现,那这句话可以被理解为“你个烦人的小妖精搞得我不要不要的”。而如果出现在母亲指责孩子,并且喋喋不休的情景下孩子的顶嘴,就应该理解为“你不要再说了我听不进去”。这就是上下文的作用,同样的内容,会被解析为不同的信息。

本文用到的例子是一串bits,如果代码想解析你为无符号整数,那这串bits就是正整数的信息;如果想解析为浮点数,那就是小数的信息,且与正整数代表的值可能完全不一样了。放大一点说,代码执行时当前的寄存器值,全局变量的值,栈帧的状态;程序运行时内存缓存的值,数据库的数据,都是它们的上下文。

程序的编译

现代编程语言具有很高的抽象程度,这是为了让人们更高效率的编写业务逻辑。而所有的程序代码都会在最终以机器码的形式执行,因为计算机只认识机器码。程序代码转换为机器码的过程大致都是如下的流程:

预处理:解掉一些语法糖,和调整部分代码,使其更方便的被编译器编译

编译器:将预处理后的代码进行编译,得到中间代码。中间代码不一定是汇编语言,也可能是C语言或其他语言,这取决于编译器的实现,一切为了效率。近几年比较流行的llvm,很多语言都基于它实现了编译器,而llvm也有它专用的中间语言IR。

汇编器:如果你实现的中间语言是汇编,那就是汇编器,否则就是其他器。这部将中间语言转换为可执行代码。可执行代码可能是计算机机器码,也有可能是某些依赖虚拟机的语言的虚拟机机器码。

链接器:代码以文件为单位进行编译。如果引用了文件外的方法,变量,则会在编译时留下一个“接口”,因为它暂时无法被确定。在链接阶段将会确定这些“接口”。

系统的硬件组成

讲了系统的硬件组成,直接看就行。比较有意思的是多层缓存机制。

进程,文件,网络,并发和并行

讲了计算机的一些代码执行和IO通信的机制。

版权所有,转载请注明出处:
https://sickworm.com/?p=440

比特币多种输出脚本(outputScript,scriptPubKey)介绍

Published / by sickworm / Leave a Comment

目前可见outputScript(scriptPubKey)格式:(参考https://bitcoin.stackexchange.com/questions/73758/what-are-the-standard-formats-of-transaction-outputs

p2pk
43 41
data(0x41):04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f ac
23 21 data(0x21):0349f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f ac

example:https://www.blockchain.com/btc/tx/7bdd7de22535770be3e14a4e527aed4431ab8adb3115657ca47df6fb1e89d70d

p2pkh

19 76a914 data(0x14):9bc6f9caddaaab28c2bc0a8bf8531f91109bdd58 88ac

p2sh

17 a914 data(0x14):9bc6f9caddaaab28c2bc0a8bf8531f91109bdd58 87

p2wpkh(bech32)

16 00 14 data(0x14):9bc6f9caddaaab28c2bc0a8bf8531f91109bdd58

p2wsh(bech32)
22 00 20 data(0x20):701a8d401c84fb13e6baf169d59684e17abd9fa216c8cc5b9fc63d622ff8c58d

p2ms
example: 2 of 3 multisig

52 // OP_2
410491bba2510912a5bd37da1fb5b1673010e43d2c6d812c514e91bfa9f2eb129e1c183329db55bd868e209aac2fbc02cb33d98fe74bf23f0c235d6126b1d8334f86
2102359c6e3f04cefbf089cf1d6670dc47c3fb4df68e2bad1fa5a369f9ce4b42bbd1
41048d2455d2403e08708fc1f556002f1b6cd83f992d085097f9974ab08a28838f07896fbab08f39495e15fa6fad6edbfb1e754e35fa1c7844c41f322a1863d46213
0395a9d84d47d524548f79f435758c01faec5da2b7e551d3b8c995b7e06326ae4a
53 // OP_3
ae // OP_CHECKMULTISIG

op_return

OP_RETURN (1 byte) PUSH (1 byte) <0 to 83 bytes of data>

others:
anyscript

说明

  1. 比特币理论上支持任意格式的script;

  2. 最主流的两种支付script为p2pkh,p2sh;隔离见证专用script为p2wpkh,p2wsh,使用新的叫bech32的编码,bech32已有官方实现:BIP173

  3. 隔离见证使用的script为p2wpkh和p2wsh两种,对应经典script的p2pkh和p2sh,但是使用隔离见证script这要求双方的钱包都支持隔离见证,所以在区块上见的不多。参考:
    https://testnet.blockchain.info/tx/f299afe17901f5a8d87f306c13f42c6fbf3d5b5de090973cf0fd34d403ccd2b8(p2wpkh转p2sh,详见4)
    https://www.blockchain.com/btc/tx/a60499338cdedebfd8cb7c379129cad1be5185d92d0db34717e66c1980a139b8(native p2wpkh)

  4. 接收方(使用utxo的一方)必须支持隔离见证,否则无法发送隔离见证交易;发送方可以不支持隔离见证,若不支持,接收方需要提供p2wpkh或p2wsh对应的p2sh脚本。这样虽然报文会稍微大一点,但是可以让不支持隔离见证的钱包发送支持隔离见证的utxo,这也是包括ledger在内主流的做法(接收地址为3开头的p2sh地址,实际使用时使用隔离见证交易)。详见BIP141BIP132

版权所有,转载请注明出处:
https://sickworm.com/?p=423

比特币隔离见证交易格式解析(Segregated witness)

Published / by sickworm / Leave a Comment

如果你还不了解经典交易构成,请看:https://blog.csdn.net/q4878802/article/details/49638457

隔离见证交易相关规范:

BIP141

BIP143

BIP144

BIP173

隔离见证 Segregated witness 交易解析

交易:https://testnet.blockchain.info/tx/f299afe17901f5a8d87f306c13f42c6fbf3d5b5de090973cf0fd34d403ccd2b8

交易报文:

01000000
00 // marker,固定值,旧交易不能txin count为0,此作为隔离见证交易格式的判断位
01 // flag,固定值,this will allow us to easily add more extra non-committed data to transactions (like txouts being spent, …). It can be interpreted as a bitvector.

// intput count
03

6f7f967a3e8c20964758efdc78e267a254b181fc3f4eab9112d885dd10e8a486 // prev tx
01000000 // prev tx index
17 16 001406c3d51e041b64e87a577ffd1a4ff5357cefd015 // scriptSig, P2WPKH nested in BIP16 P2SH <0 <20-byte-key-hash>>
// 当该utxo的前置输出是P2SH的时候就需要这样写,20字节长为对应私钥的地址,也就是witness里的公钥的hash160
ffffff00 // sequence,非ffffffff表示locktime无效

e0080049a6c62fee278ed7e11901f21b7dd9b356eedce0ce4f59c230c1e365ba
00000000
1716001406c3d51e041b64e87a577ffd1a4ff5357cefd015ffffff00

6ce4d6d1c2ee3c259989f50991f4f71c4ca96b6e986b470b9a84fd7e97c5f17d
00000000
1716001406c3d51e041b64e87a577ffd1a4ff5357cefd015ffffff00

// output count
02
00e1f50500000000 // value
17 a914 e5394e8a18db94b5e28b74f094718cab23ef9feb 87 // P2SH
a06e990700000000
17 a914 1ca5105565408eed39cdf021346313447bd99628 87

// witness P2WPKH 02 48 3045022100b6a271084b68c8b203bf708c6e725020d1e2997be2a88aef345303f62c3ce393022058ca1f83180467a3d0263a0183d28758ab797e6924c843cd797daeade984ed23 01 // sign script
21 0217cf57c2b592c9b00931370fd069b910b0b39c9f89f716d09ef614b1a3854b1c // publicKey

02 47 304402202dc1263af4dc28e2643fb5a1ceac2cd5b2d98bad3ae1d223adf809412db45ff602206c712c80be48cf60c8ce52b3757608fb66c6829f7ebcff807583380a1aff6ebd 01
21 0217cf57c2b592c9b00931370fd069b910b0b39c9f89f716d09ef614b1a3854b1c

02 47 30440220730c98896f0a4edd6ddcf5d5f1e5c04831cb1e7e6ad11e66623bc184e7242ffd02201d18e034c6764892d6dcd310488d6e9364e6abf2f7d51d31bc72ed3ac7b304ca 01
21 0217cf57c2b592c9b00931370fd069b910b0b39c9f89f716d09ef614b1a3854b1c

00000000

01000000
00
01
// input
01
b839a180196ce61747b30d2dd98551bed1ca2991377ccbd8bfdede8c339904a6
01000000
00
ffffffff

02
7dba920000000000
17 a914 9bc6f9caddaaab28c2bc0a8bf8531f91109bdd58 87 // P2SH
e31c030000000000
22 0020 701a8d401c84fb13e6baf169d59684e17abd9fa216c8cc5b9fc63d622ff8c58d // P2WSH

// witness P2WSH, 0 <1 2 CHECKMULTISIG>
04 // var_int 00, sig1, sig2,
00 // it’s a bitcoin’s bug and remain to now
47 304402204280e3c1c1edca50fb3c8843c410943937ad72f7e167e1f3fa99ff909a1b7a0502201e15e94ff9ce09cdb4cd0ab5d8bba52c408b900b8e4044a740a41eb3e8d34cff 01
48 3045022100a9b09d4f387e90b2ed2e38ea4bdecd901f611b68032566d08600868ce2b3b6a3022058c4ab2770dcea1adc301ff3f84d26e4d3e7dff3fdee1123c378c7e8d209e744 01

69 // var_int, data_length 1 + 66 + 2 = 69
52 // OP_2
210375e00eb72e29da82b89367947f29ef34afb75e8654f6ea368e0acdfd92976b7c
2103a1b26313f430c4b15bb1fdce663207659d8cac749a0e53d70eff01874496feff
2103c96d495bfdd5ba4145e3e046fee45e84a8a48ad05bd8dbb395c011a32cf9f880
53 // OP_3
ae // OP_CHECKMULTISIG

00000000

0100000000
01
01
36641869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e
01000000
23220020a16b5755f7f6f96dbd65f5f0d6ab9418b89af4b1f14a1bb8a09062c35f0dcb54
ffffffff
02
00e9a43500000000
1976a914389ffce9cd9ae88dcc0631e88a821ffdbe9bfe2688ac
c0832f0500000000
1976a9147480a33f950689af511e6e84c138dbbd3c3ee41588ac

08
00
47304402206ac44d672dac41f9b00e28f4df20c52eeb087207e8d758d76d92c6fab3b73e2b0220367750dbbe19290069cba53d096f44530e4f98acaa594810388cf7409a1870ce01
473044022068c7946a43232757cbdf9176f009a928e1cd9a1a8c212f15c1e11ac9f2925d9002205b75f937ff2f9f3c1246e547e54f62e027f64eefa2695578cc6432cdabce271502
473044022059ebf56d98010a932cf8ecfec54c48e6139ed6adb0728c09cbe1e4fa0915302e022007cd986c8fa870ff5d2b3a89139c9fe7e499259875357e20fcbb15571c76795403
483045022100fbefd94bd0a488d50b79102b5dad4ab6ced30c4069f1eaa69a4b5a763414067e02203156c6a5c9cf88f91265f5a942e96213afae16d83321c8b31bb342142a14d16381
483045022100a5263ea0553ba89221984bd7f0b13613db16e7a70c549a86de0cc0444141a407022005c360ef0ae5a5d4f9f2f87a56c1546cc8268cab08c73501d6b3be2e1e1a8a0882
4730440220525406a1482936d5a21888260dc165497a90a15669636d8edca6b9fe490d309c022032af0c646a34a44d1f4576bf6a4a74b67940f8faa84c7df9abe12a01a11e2b47

83 // OP_INVERT
cf // data_length 1 + cc + 3 = cf
56 // OP_6
210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba3
2103b28f0c28bfab54554ae8c658ac5c3e0ce6e79ad336331f78c428dd43eea8449b
21034b8113d703413d57761b8b9781957b8c0ac1dfe69f492580ca4195f50376ba4a
21033400f6afecb833092a9a21cfdf1ed1376e58c5d1f47de74683123987e967a8f4
2103a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b14862c07a1789aac16
2102d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b
56 // OP_6
ae // OP_CHECKMULTISIG
00000000

版权所有,转载请注明出处:
https://sickworm.com/?p=420

实现比特币BTC交易重发(Opt-In Replace-by-Fee,Opt-In RBF)

Published / by sickworm / Leave a Comment

当你的交易因为交易费用过低而迟迟不能被节点确认,而又没有被节点抛弃的时候,你可能需要交易重发这个功能。而交易重发实际上就是,将保存在节点交易内存池中的你的交易(因为还没被确认)替换成新的交易。

BTC交易重发的三种方法:

  1. Opt-In Replace-by-Fee,简称 Opt-In RBF 或 RBF。将更高手续费用的交易提交到节点,也是本文着重介绍的方法。具体规范:BIP125

  2. CPFP,Child Pays for Parent。使用未确认交易的输出,并给予较高手续费。此时节点如果要打包这个子交易,则必须将其低手续费的父交易也一并打包。具体策略应该是一系列交易的平均手续费(未确认)

  3. double pay,制造双花。连接上没有收录你的交易的节点,使用原来交易的输入构建新的交易,并广播出去。由于两笔交易是冲突的,所以节点只会收录其中一笔交易。最后然后祈祷该交易被收录。

各方案比较

Opt-In Replace-by-Fee 比 CPFP 费用消费低,CPFP 需要多消耗一笔交易费用的钱;

CPFP 不需要节点支持 BIP125 也可以使用,Opt-In Replace-by-Fee 需要足够多的节点支持,交易才容易被成功收录(BIP 125 已发布2年多,其实不用担心此问题);

double pay 又麻烦成功率又低,不到万不得已不使用。

Opt-In Replace-by-Fee 实现指南(参考 BIP125

交易需声明为可替换交易,声明方式分两种

  1. 显式声明:至少一个input的nSequence小于0xffffffff-1(不是小于等于)

  2. 继承声明:没有显式声明可替换的交易,但如果他们的前置交易可替换且没有被确认,那该交易也是可替换的

实现细节:(Bitcoin Core 0.12.0)

  1. 交易需要声明为可替换交易

  2. 可替换交易没有包含新的,未曾出现过在内存池中的,未确认inputs(未确认input的意思是其前置output所在的交易未确认)

  3. 新替换交易的交易费用比待替换交易费用高

  4. 新替换交易费用必须比节点的min relay fee高

  5. 待替换交易的子交易(即使用了该交易的任意outputs,该交易替换后它们将被从内存池中移出)数量不可超过100条

测试站点

使用 https://www.blockchain.com/btc/pushtx 测试通过。

测试点:

  1. 降低手续费,不提高手续费(应失败)

  2. 提高一点点手续费(应成功)

  3. 提高手续费到比找零utxo还大的值(此时会引入新utxo)(应成功)

ETH交易重发

相比 BTC,ETH 的交易重发就简单多了。只需要发布同一个 nonce 的交易,旧交易就会被替换掉。当然手续费要比以前高,矿工可不干无用功。

版权所有,转载请注明出处:
http://sickworm.com/?p=409

比特币要解决什么问题?

Published / by sickworm / Leave a Comment

本系列文章标题为码农翻身的小密圈中圈主提出的问题,下面是我跟帖的回答

比特币解决了第三方发放信用货币时可能产生的问题。

首先,人民币是有价值的。为什么这些人民币纸币有价值呢?因为这是国家发行的,而国家说他是有价值,我们人民群众也认可国家。所以,人民币可以在我们之间交易,2元人民币可以买包方便面,10元可以买包巧克力。

然后我们思考一下,人民币会永远有这样的价值吗?不一定。什么情况下人民币会失去价值?亡国了!中央银行为了解决国库空虚,无限制地增发货币!这并不是不可能,世界上某些国家曾经,甚至正在上演这样的事情。人民币有价值,是国家向我们保证人民币是没问题的,你们可以放心使用。当发行方的信任出现问题时,货币的价值也就没办法得到保证了。

往小里说,货币发行方不一定是国家。如果你信任我,你给我100块,我给你在纸上画只鸡,作为我发行的货币。我还有其他朋友也认可我画的鸡,你可以不通过我,直接拿这张纸和他交易。以后等我建立自己的国家,我的国民都会用我画的鸡做交易。
不严格地说,这张有我画的鸡的纸就是我发行的货币。如果哪一天我跑路了,或者有人发现我暗戳戳的画鸡给我的小老婆,让她拿鸡去和别人交易,我这鸡纸恐怕就没人相信了,没人愿意相信这鸡纸的价值。
因为我不再被信任,我的信用货币也不再具有价值。

而比特币是数字货币,它不靠第三方发行,也不需要信任哪个第三方。它的价值由他自身产生运行的机制作保证,任何人可对其原理进行验证。且没有人为的干扰(理论上,现实中还是有硬分叉这种充满争议的情况发生)。我们不再需要依赖那些不靠谱的人(画鸡纸的我)和国家(津巴布韦这样的)的信用,只需要证明比特币背后的机制是符合货币需求的,它就可以得到我们的信任。

版权所有,转载请注明出处:
http://sickworm.com/?p=390

给 Android ROM(AOSP)集成 SuperSU 的方法

Published / by sickworm / 给 Android ROM(AOSP)集成 SuperSU 的方法有4条评论

本文实验配置:

ROM: AOSP Android-6.0.1_r77
设备:Nexus 5
SuperSU: SR5-SuperSU-v2.82-SR5-20171001224502.zip

SuperSU 官方下载链接:https://download.chainfire.eu/1220/SuperSU/

处理 SELinux

我们给 Android 编译 ROM 的时候,可以编译出带有 root 权限的版本。但是由于 Android 4.4 以上 SELinux 的存在,apk 还是无法获得 root 权限,这样很多 root app 都会提示无法获取 root,不能正常使用了。想要 apk 可获得 root 权限,有两种方法:

  1. 关闭 SELinux 监控
  2. 配置 SELinux 权限

由于方案 2 需要熟悉复杂的 selinux 权限模型,而且我在实验过程中按网上办法硬是配置不上 domain(提示我没有设置 domain。有可能是因为我没有清空输出物,但不确定),所以我最后使用了方案 1。办法是在 $YOUR_AOSP/device/$YOUR_RAND/$YOUR_DEVICE/BoardConfig.mk 中的 BOARD_KERNEL_CMDLINE := xxxx下方加上:

BOARD_KERNEL_CMDLINE += androidboot.selinux=permissive

这样就可以使 SELinux 不阻止你的操作了,permissive 只会打日志不会做实际动作,disabled 是完全关闭。注意加上这个后会通过不了 Google 的 CTS 测试,如果你是厂家的话需要注意这一点,个人开发者不需要关心。

当然,启动完成后进入 shell,以 root 权限执行 setenforce 0 也是可以达到关闭 SELinux 监控的效果。但每次重启都要设置一遍,比较麻烦。

好了,关闭 SELinux 了。但此时你用 apk 尝试获取 root 权限,发现还是不行。因为 AOSP 的 su 是只能 shell 或者 root 用的。解决办法是:

  1. 注释掉 system/extras/su/su.c 中 main 的一行 “not allow” 的代码,这行代码会判断 uid。注释后重新 make 一次 su 就能正常使用了
  2. 使用非 AOSP 的 su,SuperSU 提供的 su 需要配合 SuperSU 其他文件,不能直接用。

然后我发现改了 su 还是不行。。我猜测 framework 层可能还有权限处理机制,那我再给 rom 集成 SuperSU 授权管理,这样总可以了把。当然你也可以每次刷 rom 后重新刷一遍第三方 recovery,再刷一遍 SuperSU。这个集成我搞了 2 天才完成,网上资料不多,而且没一个能用。。

这里提一点,如果不搞好 SELinux,集成了 SuperSU 也是没法用的。如果你不想使用方案 2,我提供几篇文章以供参考:

Compile Android 5.1.1 ROM with ROOT by SuperSU

这篇没有配置 init.rc 里面的 service 的 SELinux domain。反正我不行。

init 启动 Native Service 时出现Service xxxx needs a SELinux domain defined; please fix 警告的说明
[Android][L][SELinux]Define a SELinux domain for Service

这 2 篇教你如何配置 SELinux domain。我配置完了还是说我没配置:“init 启动 Native Service 时出现Service xxxx needs a SELinux domain defined; please fix”。上面我也提到了,可能我没 clean/clobber 才失败的,如果你尝试成功了,不妨也告诉我。

实现 SELinux | AOSP

这是 AOSP 官方对 SELinux 的介绍,在这个问题里我没看到更多的信息。

集成 SuperSU

上面这篇文章Compile Android 5.1.1 ROM with ROOT by SuperSU 也提到了集成 SuperSU 的步骤。可惜日月变迁,现在 SuperSU 已经不是单一个 su 运作了。通过翻看 SuperSU 的指南 How-To SU,我得到几个信息:

  1. 最少需要这 4 个文件,就可以保证 SuperSU 正常运行:
    /system/xbin/su
    /system/xbin/daemonsu
    /system/xbin/supolicy
    /system/lib(64)/libsupol.so
    
  2. 需要在开机时执行 daemonsu --auto-daemon,启动守护进程。

  3. 执行 daemonsu --auto-daemon 时会调用 supolicy ,然后调用 libsupol.so。用于配置 SuperSU 的 SELinux 权限。

通过翻看 SuperSU 的刷 recovery 的包里的 update-binary.sh 我得到几个信息:

  1. daemonsu 和 su 是同一个文件

  2. 开机执行 daemonsu --auto-daemon 的方法有好几种,如果有 /system/int/init.d/ 这个文件夹(我没有)就放一个脚本进去,不然就是劫持 /system/bin/app_process(64),或是给 /system/放一个 install-recovery.sh。原文 Furthermore, daemonsu --auto-daemon needs to be launched somehow on boot. This is generally done via install-recovery.sh, 99SuperSUDaemon, or hijacking app_process([32|64]).

最后这条信息告诉我们 SuperSU 不需要关闭 SELinux 也可以使用,也告诉我们集成 SELinux 而不关闭 SELinux 的办法。方法 1 由于我手机没有,所以不用;2 劫持 app_process 那个是把 app_process 链接给了 su,具体我没看懂;3 install-recovery.sh 这个文件是刷 recovery 的时候会产生的,当系统启动的时候就会执行到它,刷完就会删掉这个文件。SuperSU 利用了这个特性,在 install-recovery.sh 里执行了daemonsu --auto-daemon,而且这个文件一直存在。因为执行 install-recovery.sh 对应的是 flash_recovery 的 SELinux domain,是已经配置好的。SuperSU 通过这三种方法来绕过 SELinux,然后再通过 sepolicy 来修改 SELinux 配置。

而我这边因为一直都是配置在 init.rc 里,且关闭了 SELinux,所以没有用到上面提到的方案。

集成步骤(在 Compile Android 5.1.1 ROM with ROOT by SuperSU 基础上修改)

  1. 删除原 su。文件位置 system\extras\su,最简单的方法是把该目录下的 Android.mk 重命名或者删掉。

  2. 添加 SuperSU 相关文件。包括上面提到的 4个 Linux 文件,和一个 SuperSU.apk。Linux 文件我选择在 packages 下新建了一个 su,放入上面那4个文件,以及创建 Android.mk。我比较懒,就没有做架构选择,就只把自己的 Nexus 5 对应的 armv7 包里的文件拷过来了,suinit 和 sukernel 不需要,复制一份 su 改名为 daemonsu。Android.mk 内容如下:

    LOCAL_PATH := $(call my-dir)
    
    include $(CLEAR_VARS)
    
    LOCAL_MODULE_TAGS := optional
    LOCAL_MODULE := su
    LOCAL_SRC_FILES := $(LOCAL_MODULE)
    LOCAL_MODULE_CLASS := EXECUTABLES
    LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
    LOCAL_UNSTRIPPED_PATH := $(LOCAL_MODULE_PATH)
    include $(BUILD_PREBUILT)
    
    
    include $(CLEAR_VARS)
    
    LOCAL_MODULE_TAGS := optional
    LOCAL_MODULE := daemonsu
    LOCAL_SRC_FILES := $(LOCAL_MODULE)
    LOCAL_MODULE_CLASS := EXECUTABLES
    LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
    LOCAL_UNSTRIPPED_PATH := $(LOCAL_MODULE_PATH)
    include $(BUILD_PREBUILT)
    
    
    include $(CLEAR_VARS)
    
    LOCAL_MODULE_TAGS := optional
    LOCAL_MODULE := supolicy
    LOCAL_SRC_FILES := $(LOCAL_MODULE)
    LOCAL_MODULE_CLASS := EXECUTABLES
    LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES)
    LOCAL_UNSTRIPPED_PATH := $(LOCAL_MODULE_PATH)
    include $(BUILD_PREBUILT)
    
    
    include $(CLEAR_VARS)
    
    LOCAL_MODULE_TAGS := optional
    LOCAL_MODULE := libsupol.so
    LOCAL_MODULE_CLASS := SHARED_LIBRARIES
    LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)
    LOCAL_SRC_FILES := $(LOCAL_MODULE)
    OVERRIDE_BUILD_MODULE_PATH := $(TARGET_OUT_INTERMEDIATE_LIBRARIES)
    include $(BUILD_PREBUILT)
    

    apk 我放在了 packages/apps/SuperSU,同样的,放入 Superuser.apk(上面的官方刷机包里有),同时创建 Android.mk,内容如下:

    LOCAL_PATH := $(call my-dir)
    include $(CLEAR_VARS)
    
    LOCAL_MODULE := SuperSU
    
    LOCAL_SRC_FILES := Superuser.apk
    LOCAL_MODULE_CLASS := APPS
    LOCAL_MODULE_SUFFIX := $(COMMON_ANDROID_PACKAGE_SUFFIX)
    LOCAL_CERTIFICATE := PRESIGNED
    
    include $(BUILD_PREBUILT)
    
  3. 把第 2 步添加的 packages 添加到编译路径中。我只给 Nexus 5 设备添加了(这样不好,因为第一步把所有设备的 su 都删掉了)。修改 $YOUR_AOSP/device/$YOUR_RAND/$YOUR_DEVICE/device.mk,添加:
    PRODUCT_PACKAGES += \
         power.hammerhead
    
    +# SuperSU
    +#PRODUCT_PACKAGES += \
    +#    su \
    +#    daemonsu \
    +#    supolicy \
    +#    libsupol.so \
    +#    SuperSU
    
  4. 添加相关文件权限。修改 system/core/libcutils/fs_config.c,寻找 “system/xbin/su”,修改:
    -    { 04750, AID_ROOT,      AID_SHELL,     0, "system/xbin/su" },
    +    { 06755, AID_ROOT,      AID_ROOT,     0, "system/xbin/su" },
    +    { 07777, AID_ROOT,      AID_ROOT,     0, "system/xbin/daemonsu" },
    +    { 06755, AID_ROOT,      AID_ROOT,     0, "system/xbin/supolicy" },
    
  5. 在 system/core/rootdir/init.rc 中添加服务:
    service console /system/bin/sh
         class core
         console
         disabled
    -    user shell
    -    group shell log
    +    user root
    +    group root 
         seclabel u:r:shell:s0
    
    service installd /system/bin/installd
         class main
         socket installd stream 600 system system
    
    +# SuperSU
    +service daemonsu /system/xbin/daemonsu --auto-daemon &
    +    class main
    +    oneshot
    +
     service flash_recovery /system/bin/install-recovery.sh
         class main
         oneshot
    
  6. 编译,刷进去。自此 apk 可通过 SuperSU 获得 root 权限!

存在问题

由于对 AOSP 不熟悉,文件放置不太讲究,不能迎合多设备编译的需求。

还有一个小问题,就是点击 SuperSU 进入主界面时会提示有新 SU 可用,可是我已经下载最新版本了。我估计因为这是最小系统,SuperSU 发现有些文件缺失所以做出提示。

此时注意:不可以点击 INSTALL!因为点击 install SuperSU 会把 install-recovery.sh 加到文件系统里,而我本来又在 init.rc 里写过一次启动了,这会导致多次启动 daemonsu,结果是系统起不来(也可能是别的原因,但至少可以确定的是当我没有在 init.rc 配置启动 daemonsu,而是手动更新的时候,此时点击 INSTALL 系统是能正常启动的)。如果用到 SuperSU 提到的那三种办法,估计就不会多次启动了。因为平时也不需要打开 SuperSU,我就不深究下去了,毕竟编译花时间。

版权所有,转载请注明出处:
http://sickworm.com/?p=367

下载 Android source code(AOSP)遇到的一些问题及解决方法

Published / by sickworm / 下载 Android source code(AOSP)遇到的一些问题及解决方法有1条评论

最近在搞 apk 爆破工程,经常需要调试别人的 apk,每次手动修改 apk 的 debuggable 属性比较麻烦,而且要有时候还不成功。所以还是一劳永逸,下载 AOSP ,把 ro.debuggable 打开,编一个 Nexus 5 的镜像给我手机用。关于 apk 调试的参考链接:https://www.0xaa55.com/technews/201602/00000215.html

建议使用清华镜像,免翻墙。教程链接:https://mirrors.tuna.tsinghua.edu.cn/help/AOSP/

下面是我在 windows 下,使用cygwin 下载官方 AOSP 时遇到的问题及解决办法:(在 windows 下载主要是为了方便我做别的事情,AOSP 官网上说 repo 只支持 linux 和 mac OS,cygwin 理论上也是支持的,但要填一些坑)

1. repo init 失败,request time out / 404

原因是没有翻墙。我使用的是 Proxifier + shadowsocks ,可以全局翻墙。 或者用普通的 VPN 也可以。网上方法是修改 repo 内容,增加 ss 翻墙配置的;也有修改镜像 url,改成国内的。我在 mac 上试过,部分链接还是被墙,没有成功。

2. 使用 cygwin 的 python 无法运行,报错 no module named site / no module named sysconfig / no module named fcntl;或者是 repo init 时 Get 完第一个之后没有预兆直接退出

这个问题可能是好几个原因造成的。首先,cygwin 是会继承 windows 的环境变量 PATH,所以 cygwin 可能会直接用你 windows 下配置的 python。这会带来几个问题:

  1. 直接输入 python 的 play ground 不能正常显示了(没研究具体原因)

  2. repo init 时提示 Get xxx.bundle 后直接退出。我跟了一下 repo 的代码,是 repo 构造 git clone 命令不对,其路径是 Windows 的路径,而不是 cygwin 的路径。

  3. 运行 repo init 时提示 no module named fcntl。上 google 查了一下,有回答说 Windows 没有 fcntl 这个 python 库。这个回答让我放弃了直接用 windows shell 运行 repo 的想法。(最后发现是存在的,不然 cygwin 也没办法运行 fcntl,因为 cygwin 不是 linux 虚拟机,本质也是 windows 的东西。因为网上说 Windows 没有 fcntl 放弃 windows shell,而尝试 cygwin 运行 repo,也是一个挺蠢的想法)

所以需要切换到 cygwin 的 python 。安装方法可以直接运行 cygwin 的 setup,搜索 python 下载。或使用 apt-cyg (需另外安装,网上有教程)执行 “`apt-cyg install python““。安装完成后还需要把 cygwin 的 $PATH 变量修改一下,把 windows 下的 python 路径剔除掉(我这里是 /cygdriver/d/Python27),否则还是会优先使用 Windows 下的 python。修改方法直接在 .bashrc 或 .bash_profile 下改就可以了。切换过来后,后还可能出现问题:

  1. 运行 python 报错 no module named site / no module named sysconfig

原因是 python 包路径错了,你可以输入 “import sys(回车)print sys.path “看一下。我这里就是莫名其妙多了当前目录的路径前缀。

解决办法是为cygwin 设置正确的路径,并写入环境变量 PYTHONPATH 中。我写的是/lib/python27.zip:/lib/python2.7:/lib/python2.7/plat-cygwin:/lib/python2.7/lib-tk:/lib/python2.7/lib-old:/lib/python2.7/lib-dynload

下面是我在 mac 下编译遇到的问题及解决办法:

首先官网上的环境准备要先做好,参考下面链接的 Setting up a Mac OS build environment 章节。防止意外,里面提到的 gmake 降级我都做了。
https://source.android.com/source/initializing

1. build/core/combo/mac_version.mk: Can not find SDK 10.6 at XXX

写这篇文章时 SDK 已经去到 10.12 了,而打开build/core/combo/mac_version.mk 一看,上面写着 supported versions 只支持 10.6 10.7 10.8 10.9。我直接在 supported version 上加了 10.12。结果遇到第二个问题。

2. desperate method XXXX

具体方法名字我忘了,说是 10.12 这个方法已经废弃了。那没办法,搜了一下 SDK 可以从网上下载。下载链接https://github.com/phracker/MacOSX-SDKs/releases

参考文章,教你如何放置 SDK 到正确路径:
http://www.jianshu.com/p/1513fc9e1a74

我看既然是找不到 10.6了,那就直接下 10.6 吧!结果出了第三个问题。

3. no member named llrintl / no member named llroundl

编译器说只有 lrintl 没有 llrintl。我跑去 MacOS SDK 里面看,有 llrintl,但是被宏控制着,因为其不是 C90 标准,需要加 -srd=c99 才可以。但要我找到调用编译的位置实在太麻烦了。

继续 google,有人说 10.11 10.9 都成功了,那我下一个 10.9放进去吧。结果还是提示找不到 10.6。

说好的 supported versions 呢?!我生气的吧 supported versions 中的 10.6 10.7 10.8 都删掉了,10.6 的 SDK 目录也删了,只留了一个 10.9。成功!

4. 切换分支时遇到:error.GitError: manifests rev-list (‘^HEAD’, ‘XXXXX’, ‘–‘): fatal: bad revision ‘^HEAD’

原因可能有好几个,我用了网上的方法都没有凑效。这个错误在我这里是 .git 的 HEAD 值丢失了,至于为什么我也不知道。这条语句的意思是:

在 manifests 这个 git 项目中执行 git rev-list ^HEAD XXXXX — 这个命令时,报错 fatal: bad revision ‘^HEAD’,即错误的版本 HEAD,意思是 HEAD 对应的 git 版本不正确。其中 manifests 这个工程在 .repo/manifests 中。 HEAD 对应的 git 版本存储在 .repo/manifests/.git/HEAD 中,这个 HEAD 文件的值为 ref: refs/heads/default。然后发现并没有 .repo/manifests/.git/heads/default 这个文件。解决办法:在其他目录重新 repo init 一次,把这个文件拷过来即可。

奇怪的是,我之前按照 http://blog.leanote.com/post/gyhlqq@gmail.com/Android-repo-sync-issue-fatal-bad-revision-HEAD-%E8%A7%A3%E5%86%B3%E6%96%B9%E6%A1%88 将整个 repo init 相关的文件都覆盖过去了,这个文件应该也复制过去才对,结果没有。

嗯。。我傻逼了,cp 命令的 src 为目录时,不是拷贝目录,而是把目录下的所有文件拷贝过去。还是推荐上面链接的做法,因为不止这一处会出问题,直接整个覆盖是最吼的。

版权所有,转载请注明出处:

http://sickworm.com/?p=346