Locate system linker section automatically

This commit is contained in:
Mygod
2020-08-12 10:31:41 -04:00
parent 015510d770
commit 44ba43389d

View File

@@ -5,6 +5,7 @@ import android.os.Debug
import android.os.Process
import androidx.annotation.RequiresApi
import java.io.File
import java.io.IOException
object AppProcess {
/**
@@ -32,7 +33,49 @@ object AppProcess {
return "/system/etc/ld.config.txt"
}
/**
* Based on: https://android.googlesource.com/platform/bionic/+/30f2f05/linker/linker_config.cpp#182
*/
@RequiresApi(29)
fun findLinkerSection(lines: Sequence<String>, binaryRealPath: String): String {
for (untrimmed in lines) {
val line = untrimmed.substringBefore('#').trim()
if (line.isEmpty()) continue
if (line[0] == '[' && line.last() == ']') break
if (line.contains("+=")) continue
val chunks = line.split('=', limit = 2)
if (chunks.size < 2) {
Logger.me.w("warning: couldn't parse invalid format: $line (ignoring this line)")
continue
}
var (name, value) = chunks.map { it.trim() }
if (!name.startsWith("dir.")) {
Logger.me.w("warning: unexpected property name \"$name\", " +
"expected format dir.<section_name> (ignoring this line)")
continue
}
if (value.endsWith('/')) value = value.dropLast(1)
if (value.isEmpty()) {
Logger.me.w("warning: property value is empty (ignoring this line)")
continue
}
try {
value = File(value).canonicalPath
} catch (e: IOException) {
Logger.me.i("warning: path \"$value\" couldn't be resolved: ${e.message}")
}
if (binaryRealPath.startsWith(value) && binaryRealPath[value.length] == '/') return name.substring(4)
}
throw IllegalArgumentException("No valid linker section found")
}
val myExe get() = "/proc/${Process.myPid()}/exe"
val myExeCanonical get() = try {
File("/proc/self/exe").canonicalPath
} catch (e: IOException) {
Logger.me.i("warning: couldn't resolve self exe: ${e.message}")
"/system/bin/app_process"
}
/**
* To workaround Samsung's stupid kernel patch that prevents exec, we need to relocate exe outside of /data.
@@ -51,10 +94,17 @@ object AppProcess {
// unfortunately native ld.config.txt only recognizes /data,/system,/system_ext as system directories;
// to link correctly, we need to add our path to the linker config too
val ldConfig = "$apexPath/etc/ld.config.txt"
val masterLdConfig = genericLdConfigFilePath
val section = try {
File(masterLdConfig).useLines { findLinkerSection(it, myExeCanonical) }
} catch (e: Exception) {
Logger.me.w("Failed to locate system section", e)
"system"
}
script.appendln("[ -f $ldConfig ] || " +
"mkdir -p $apexPath/etc && " +
"echo dir.system = $apexPath >$ldConfig && " +
"cat $genericLdConfigFilePath >>$ldConfig || exit 1")
"echo dir.$section = $apexPath >$ldConfig && " +
"cat $masterLdConfig >>$ldConfig || exit 1")
"$apexPath/bin" to "$apexPath/bin/app_process"
}
script.appendln("[ -f $relocated ] || " +
@@ -64,7 +114,11 @@ object AppProcess {
return script to relocated
}
fun launchString(packageCodePath: String, clazz: String, appProcess: String, niceName: String?): String {
/**
* Compute the shell script line that exec into the corresponding [clazz].
* Extra params can be simply appended to the string.
*/
fun launchString(packageCodePath: String, clazz: String, appProcess: String, niceName: String? = null): String {
val debugParams = if (Debug.isDebuggerConnected()) when (Build.VERSION.SDK_INT) {
in 29..Int.MAX_VALUE -> "-XjdwpProvider:adbconnection"
28 -> "-XjdwpProvider:adbconnection -XjdwpOptions:suspend=n,server=y -Xcompiler-option --debuggable"