1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0 2*6db59d35SArnaldo Carvalho de Melo #include <inttypes.h> 3203d8a4aSSong Shan Gong #include <unistd.h> 4203d8a4aSSong Shan Gong #include <stdio.h> 5203d8a4aSSong Shan Gong #include <string.h> 620f2be1dSJiri Olsa #include <internal/lib.h> // page_size 7203d8a4aSSong Shan Gong #include "machine.h" 8203d8a4aSSong Shan Gong #include "api/fs/fs.h" 96738028dSThomas Richter #include "debug.h" 10b9c0a649SThomas Richter #include "symbol.h" 11203d8a4aSSong Shan Gong 1212a6d294SThomas Richter int arch__fix_module_text_start(u64 *start, u64 *size, const char *name) 13203d8a4aSSong Shan Gong { 146738028dSThomas Richter u64 m_start = *start; 15203d8a4aSSong Shan Gong char path[PATH_MAX]; 16203d8a4aSSong Shan Gong 17203d8a4aSSong Shan Gong snprintf(path, PATH_MAX, "module/%.*s/sections/.text", 18203d8a4aSSong Shan Gong (int)strlen(name) - 2, name + 1); 196738028dSThomas Richter if (sysfs__read_ull(path, (unsigned long long *)start) < 0) { 206738028dSThomas Richter pr_debug2("Using module %s start:%#lx\n", path, m_start); 216738028dSThomas Richter *start = m_start; 2212a6d294SThomas Richter } else { 2312a6d294SThomas Richter /* Successful read of the modules segment text start address. 2412a6d294SThomas Richter * Calculate difference between module start address 2512a6d294SThomas Richter * in memory and module text segment start address. 2612a6d294SThomas Richter * For example module load address is 0x3ff8011b000 2712a6d294SThomas Richter * (from /proc/modules) and module text segment start 2812a6d294SThomas Richter * address is 0x3ff8011b870 (from file above). 2912a6d294SThomas Richter * 3012a6d294SThomas Richter * Adjust the module size and subtract the GOT table 3112a6d294SThomas Richter * size located at the beginning of the module. 3212a6d294SThomas Richter */ 3312a6d294SThomas Richter *size -= (*start - m_start); 346738028dSThomas Richter } 35203d8a4aSSong Shan Gong 36203d8a4aSSong Shan Gong return 0; 37203d8a4aSSong Shan Gong } 38b9c0a649SThomas Richter 39b9c0a649SThomas Richter /* On s390 kernel text segment start is located at very low memory addresses, 40b9c0a649SThomas Richter * for example 0x10000. Modules are located at very high memory addresses, 41b9c0a649SThomas Richter * for example 0x3ff xxxx xxxx. The gap between end of kernel text segment 42b9c0a649SThomas Richter * and beginning of first module's text segment is very big. 43b9c0a649SThomas Richter * Therefore do not fill this gap and do not assign it to the kernel dso map. 44b9c0a649SThomas Richter */ 45b9c0a649SThomas Richter void arch__symbols__fixup_end(struct symbol *p, struct symbol *c) 46b9c0a649SThomas Richter { 47b9c0a649SThomas Richter if (strchr(p->name, '[') == NULL && strchr(c->name, '[')) 48b9c0a649SThomas Richter /* Last kernel symbol mapped to end of page */ 49b9c0a649SThomas Richter p->end = roundup(p->end, page_size); 50b9c0a649SThomas Richter else 51b9c0a649SThomas Richter p->end = c->start; 52*6db59d35SArnaldo Carvalho de Melo pr_debug4("%s sym:%s end:%#" PRIx64 "\n", __func__, p->name, p->end); 53b9c0a649SThomas Richter } 54