I am developing a program under Linux.
For debugging purposes I want to trace all calls from my program to a certain (preferably shared) library. (I do not want to trace calls happening inside the library.)
For syscalls there is strace. Is there any instrument to trace calls to a shared library?
The tool you are looking for is called ltrace. It allows to trace any call from the program to all (or a set of given) libraries.
For example, the following call will list any call to an external function loaded by a shared library:
$> ltrace ls /
__libc_start_main(0x4028c0, 2, 0x7fff1f4e72d8, 0x411e60 <unfinished ...>
strrchr("ls", '/') = nil
setlocale(LC_ALL, "") = "en_US.UTF-8"
bindtextdomain("coreutils", "/usr/share/locale") = "/usr/share/locale"
textdomain("coreutils") = "coreutils"
__cxa_atexit(0x40a200, 0, 0, 0x736c6974756572) = 0
isatty(1) = 0
getenv("QUOTING_STYLE") = nil
getenv("COLUMNS") = nil
ioctl(1, 21523, 0x7fff1f4e6e80) = -1
getenv("TABSIZE") = nil
getopt_long(2, 0x7fff1, "abcdfghiklmnopqrstuvw:xABCDFGHI:"..., 0x413080, -1) = -1
...
+++ exited (status 0) +++
If you want to focus on a particular library, then you should use the --library=pattern option:
-l, --library library_pattern
Display only calls to functions implemented by libraries that match
library_pattern. Multiple library patterns can be specified with several
instances of this option. Syntax of library_pattern is described in
section FILTER EXPRESSIONS.
Note that while this option selects calls that might be directed to the
selected libraries, there's no actual guarantee that the call won't be
directed elsewhere due to e.g. LD_PRELOAD or simply dependency ordering.
If you want to make sure that symbols in given library are actually called,
use -x #library_pattern instead.
So, for example, getting the list of calls to libselinux.so.1 is done like this:
$ ltrace -l libselinux.so.1 ls /
ls->freecon(0, 0xffffffff, 0x7f78c4eee628, 0) = 0
bin dev media root sbin sys usr boot etc home lib lost+found proc run tmp
+++ exited (status 0) +++
Only one call to the function freecon() is taken out this run.
Related
I am interested in /proc/sys and trying to understand the access control mechanism of files in this directory.
I am not sure if accessing /proc/sys is the same as accessing on-disk file systems, like ext4. So I just started with the open system call and tried to trace critical kernel functions called among the process.
And found that it first called do_sys_open(), which called do_filp_open() internally. In do_filp_open(), some path name resolution is done at first and then it called may_open() to do some permission checks, and finally vfs_open() is called to do the specific open function according to the file system.
From reading the source code, I suppose the permission check work is indeed done by generic_permission() which located in /fs/namei.c. The whole function looks like this:
int generic_permission(struct inode *inode, int mask)
{
int ret;
/*
* Do the basic permission checks.
*/
ret = acl_permission_check(inode, mask);
if (ret != -EACCES)
return ret;
if (S_ISDIR(inode->i_mode)) {
/* DACs are overridable for directories */
if (capable_wrt_inode_uidgid(inode, CAP_DAC_OVERRIDE))
return 0;
if (!(mask & MAY_WRITE))
if (capable_wrt_inode_uidgid(inode,
CAP_DAC_READ_SEARCH))
return 0;
return -EACCES;
}
/*
* Read/write DACs are always overridable.
* Executable DACs are overridable when there is
* at least one exec bit set.
*/
if (!(mask & MAY_EXEC) || (inode->i_mode & S_IXUGO))
if (capable_wrt_inode_uidgid(inode, CAP_DAC_OVERRIDE))
return 0;
/*
* Searching includes executable on directories, else just read.
*/
mask &= MAY_READ | MAY_WRITE | MAY_EXEC;
if (mask == MAY_READ)
if (capable_wrt_inode_uidgid(inode, CAP_DAC_READ_SEARCH))
return 0;
return -EACCES;
}
So, it seems like UGO check comes at first, if UGO failed kernel will check if you have special Capability. But this process is not consistent with the experiment result I saw when I tried access files under /proc/sys. Take /proc/sys/kernel/usermodehelper/bset as an example:
$ ll /proc/sys/kernel/usermodehelper/bset
-rw------- 1 root root 0 Nov 6 12:15 /proc/sys/kernel/usermodehelper/bset
This file is owned by root and can’t be read from others. From the logic in generic_permission(), non-root could read this file if he has CAP_DAC_OVERRIDE. So I give /bin/cat CAP_DAC_OVERRIDE, but got an “Permission denied” and still cannot read the file.However, I could read /etc/shadow after grand CAP_DAC_OVERRIDE to cat, which is also a root file and can't be read by a normal user.
Why did this happen?What is the permission check process like when accessing files under /proc/sys? Doesn’t it go through generic_permission()? Is there some other check in kernel when accessing /proc/sys?
I am working on implementation of new fiscal device. And it is using OPOS / UPOS library for communication. I am very new to ctypes and have no experience with C at all. However, I have managed to make it work, mostly.
But I am having issues with returning a string from generalist method DirectIO. documentation says: "This command should be used immediately after EndFiscalReceipt() to retrieve unique ID of latest receipt"
" Parameters:
– Data [in]
Ignored.
– Obj [in/out]
Value to be read."
And adds .NET example under it:
int iData = 0;
string strReferenceID = "";
fiscalPrinter.EndFiscalReceipt();
fiscalPrinter.DirectIO(CMD_EKASA_RECEIPT_ID, ref iData, ref strReferenceID);
// strReferenceID will contain latest receipt ID, e.g. "O−7DBCDA8A56EE426DBCDA8A56EE426D1A"
the first parameter (CMD_EKASA_RECEIPT_ID) is the command executed, thats why its not listed above.
However, python is not .NET and I have never been working with .NET.
I have been following instructions in ctypes doku (https://docs.python.org/2.7/library/ctypes.html), defiend this methods arguments and return in init:
self.libc.DirectIO.argtypes = [ctypes.c_int32, ctypes.c_int32, ctypes.c_char_p]
self.libc.DirectIO.restype = ctypes.c_char_p
Than tried different ways to retrieve reply string, but neither of these does work in my case:
s = ""
c_s = ctypes.c_char_p(s)
result = self.send_command(CMD_EKASA_RECEIPT_ID, 0, c_s)
p = ctypes.create_string_buffer(40)
poin = ctypes.pointer(p)
result = self.send_command(CMD_EKASA_RECEIPT_ID, 0, poin)
p = ctypes.create_string_buffer(40)
result = self.send_command(CMD_EKASA_RECEIPT_ID, 0, p)
s = ctypes.create_string_buffer('\000' * 32)
result = self.send_command(CMD_EKASA_RECEIPT_ID, 0, s)
the string object I have created is allways empty, a.k.a. "" after caling the Cmethod, just like I have created it.
However, there is one more thing, that does not make sense to me. My colleague showed me, how you can see method arguments and return in header file. For this one, there is this:
int DirectIO(int iCommand, int* piData, const char* pccString);
Which means, it returns integer? If I am not mistaken.
so, what I am thinking is, that I have to pass to the method some pointer to a string, created in python, and C will change it, into what I should read. Thus, I think my way of thinking about solution is right.
I have also tried this approach, but that does not work for me either How to pass pointer back in ctypes?
and I am starting to feel desperate. Not sure if I understand the problem correctly and looking for a solution is right place.
I have solved my problem. The whole thing was, in allocating of memory. Every example on the net that I have readed did create empty string, like s = "". But, that is not correct!
When allocated empty string "" C library have had no memory where to write result.
this was almost correct approach,
self.libc = ctypes.cdll.LoadLibrary(LIB_PATH)
self.libc.DirectIO.argtypes = [ctypes.c_int32, ctypes.c_int32, ctypes.c_char_p]
result_s = ctypes.c_char_p("")
log.info('S address: %s | S.value: "%s"' % (result_s, result_s.value))
self.libc.DirectIO(CMD_EKASA_RECEIPT_ID, 0, result_s)
log.info('S address: %s | S.value: "%s"' % (result_s, result_s.value))
returns:
S address: c_char_p(140192115373700) | S.value: ""
S address: c_char_p(140192115373700) | S.value: ""
it needed just a small modification:
self.libc = ctypes.cdll.LoadLibrary(LIB_PATH)
self.libc.DirectIO.argtypes = [ctypes.c_int32, ctypes.c_int32, ctypes.c_char_p]
result_s = ctypes.c_char_p(" " * 10)
log.info('S address: %s | S.value: %s' % (result_s, result_s.value))
self.libc.DirectIO(CMD_EKASA_RECEIPT_ID, 0, result_s)
log.info('S address: %s | S.value: %s' % (result_s, result_s.value))
now, printing result_s after calling self.libc.DirectIO does return different string, than it was before call.
S address: c_char_p(140532072777764) | S.value: " "
S address: c_char_p(140532072777764) | S.value: "0-C12A22F5"
There is linux in the tag, but OPOS does not work on linux.
Or are you working in an emulation environment such as Wine?
In any case, if you don't have the right environment, you can get into trouble with a little bit of nothing.
First, work in a Windows 32-bit environment, create something that works there, and then port it to another environment.
Since OPOS uses OLE/COM technology, the first package to use is win32com or comtypes.
UnifiedPOS is a conceptual specification and there are no actual software components.
There are three types of software that actually run: OPOS, JavaPOS, and POS for.NET.
OPOS and POS for.NET only work in a Windows 32-bit environment.
Only JavaPOS can work in a Linux environment, and it is usually only available from Java.
If you want to make something in Python, you need to create a Wrapper (or glue) library that calls Java from Python.
If the C interface UnifiedPOS(OPOS) is running on Linux without using the Windows emulator or the Wrapper for Java, it may be an original library/component created by the printer vendor with reference to UnifiedPOS.
In that case, I think that the detailed specification can only be heard from the vendor who created it.
To explain, DirectIO method and DirectIOEvent are defined as method/event that vendors can freely define and use.
Therefore, only method/event names and parameters are defined in the UnifiedPOS document.
It is necessary to ask the vendor who provides the DirectIO method/DirectIOEvent what function the specific vendor's service object has, and it is up to the vendor to determine what the parameter means is.
The OPOS specification was absorbed by UnifiedPOS from the middle, but until then it existed as a single specification.
The rest of the name is here. MCS: OPOS Releases
This is the root of the return value of the method of your library being integer.
By the way, this is the latest UnifiedPOS specification for now.
Document -- retail/17-07-32 (UnifiedPOS Retail Peripheral Architecture, Version 1.14.1)
When attempting to install the Octave io package on Windows 7 I receive the following error:
>> pkg install io-2.4.12.tar.gz
0 [main] us 0 init_cheap: VirtualAlloc pointer is null, Win32 error 487
AllocationBase 0x0, BaseAddress 0x60EA0000, RegionSize 0x190000, State 0x10000
C:\Octave\Octave-4.2.0\bin\perl.exe: *** Couldn't reserve space for cygwin's heap, Win32 error 0
warning: doc_cache_create: unusable help text found in file 'getxmlattv'
For information about changes from previous versions of the io package, run 'news io'.
>>
I have a read a few other similar questions but have been unable to find an answer, and I do not understand the error message in all honesty. I understand cygwin in a Unix-like interface for windows, but that is about it. I have tried running as administrator, deleting all temp files, restarting etc. but cannot get the pkg to install successfully. Any ideas?
The referenced file 'getxmlattv' is just a function and not a text file as described and cannot be run as a standalone file:
function [retval] = getxmlattv (xmlnode, att)
retval = '';
## Get end of first tag
iend = index (xmlnode, ">");
## Get start of value string. Concat '="' to ensure minimal ambiguity
vals = index (xmlnode, [att '="']);
if (vals == 0)
## Attribute not in current tag
return
elseif (vals)
vals = vals + length (att) + 2;
vale = regexp (xmlnode(vals:end), '"[ >/]');
if (! isempty (vale))
retval = xmlnode(vals:vals+vale-2);
endif
endif
endfunction
I don't see how this is of any use.
For the windows version of octave the packages are already available in the installer
https://wiki.octave.org/Octave_for_Microsoft_Windows
so you don't need to install io from source package. Just re-run the installer
if you missed it.
Please note that the error message is misleading as you are not using the
cygwin version of octave but msys/mingw one; that is based on a modified
version of the cygwin1.dll where they forgot to update the messages:
$ strings msys-1.0.dll | grep cygwin
...
%P: *** Couldn't reserve space for cygwin's heap (%p <%p>) in child, %E
...
need_resched:
preempt_disable();
cpu = smp_processor_id();
rq = cpu_rq(cpu);
rcu_note_context_switch(cpu);
prev = rq->curr;
switch_count = &prev->nivcsw;
release_kernel_lock(prev);
I would like to ask is: "need_resched:" What is the role.
In detail,The linux kernel version is 2.6.35.3.
need_schedule: is simply a label. Later in the code you will find:
if (need_resched())
goto need_resched;
I.e., if the rescheduling flag ist set (what is tested by need_reschedule()), this point in code is executed (again).
I'm looking to monkey-patch require() to replace its file loading with my own function. I imagine that internally require(module_id) does something like:
Convert module_id into a file path
Load the file path as a string
Compile the string into a module object and set up the various globals correctly
I'm looking to replace step 2 without reimplementing steps 1 + 3. Looking at the public API, there's require() which does 1 - 3, and require.resolve() which does 1. Is there a way to isolate step 2 from step 3?
I've looked at the source of require mocking tools such as mockery -- all they seem to be doing is replacing require() with a function that intercepts certain calls and returns a user-supplied object, and passes on other calls to the native require() function.
For context, I'm trying to write a function require_at_commit(module_id, git_commit_id), which loads a module and any of that module's requires as they were at the given commit.
I want this function because I want to be able to write certain functions that a) rely on various parts of my codebase, and b) are guaranteed to not change as I evolve my codebase. I want to "freeze" my code at various points in time, so thought this might be an easy way of avoiding having to package 20 copies of my codebase (an alternative would be to have "my_code_v1": "git://..." in my package.json, but I feel like that would be bloated and slow with 20 versions).
Update:
So the source code for module loading is here: https://github.com/joyent/node/blob/master/lib/module.js. Specifically, to do something like this you would need to reimplement Module._load, which is pretty straightforward. However, there's a bigger obstacle, which is that step 1, converting module_id into a file path, is actually harder than I thought, because resolveFilename needs to be able to call fs.exists() to know where to terminate its search... so I can't just substitute out individual files, I have to substitute entire directories, which means that it's probably easier just to export the entire git revision to a directory and point require() at that directory, as opposed to overriding require().
Update 2:
Ended up using a different approach altogether... see answer I added below
You can use the require.extensions mechanism. This is how the coffee-script coffee command can load .coffee files without ever writing .js files to disk.
Here's how it works:
https://github.com/jashkenas/coffee-script/blob/1.6.2/lib/coffee-script/coffee-script.js#L20
loadFile = function(module, filename) {
var raw, stripped;
raw = fs.readFileSync(filename, 'utf8');
stripped = raw.charCodeAt(0) === 0xFEFF ? raw.substring(1) : raw;
return module._compile(compile(stripped, {
filename: filename,
literate: helpers.isLiterate(filename)
}), filename);
};
if (require.extensions) {
_ref = ['.coffee', '.litcoffee', '.md', '.coffee.md'];
for (_i = 0, _len = _ref.length; _i < _len; _i++) {
ext = _ref[_i];
require.extensions[ext] = loadFile;
}
}
Basically, assuming your modules have a set of well-known extensions, you should be able to use this pattern of a function that takes the module and filename, does whatever loading/transforming you need, and then returns an object that is the module.
This may or may not be sufficient to do what you are asking, but honestly from your question it sounds like you are off in the weeds somewhere far from the rest of the programming world (don't take that harshly, it's just my initial reaction).
So rather than mess with the node require() module, what I ended up doing is archiving the given commit I need to a folder. My code looks something like this:
# commit_id is the commit we want
# (note that if we don't need the whole repository,
# we can pass "commit_id path_to_folder_we_need")
#
# path is the path to the file you want to require starting from the repository root
# (ie 'lib/module.coffee')
#
# cb is called with (err, loaded_module)
#
require_at_commit = (commit_id, path, cb) ->
dir = 'old_versions' #make sure this is in .gitignore!
dir += '/' + commit_id
do_require = -> cb null, require dir + '/' + path
if not fs.existsSync(dir)
fs.mkdirSync(dir)
cmd = 'git archive ' + commit_id + ' | tar -x -C ' + dir
child_process.exec cmd, (error) ->
if error
cb error
else
do_require()
else
do_require()