Sunday, April 24, 2016

How to Enable GDB on Mac OS X El Capitan

I have a macbook air (MBA) which I carry around to use at various locations other than my desk at home. Of course I could install Ubuntu on my MBA, but I really like how easy it is to do anything on OS X,  so I am keeping it. I also do a lot of software development on my MBA. That being said, it bothers me that by default I cannot run gdb on OS X El Capitan. In this post, I will show how to enable gdb on OS X El Capitan. The credit goes to here.

First, you will need to install gdb. I would use brew. In case you don't have brew installed on the system, follow the instructions here.
$ brew install gdb

When you try to run a program on gdb, you will encounter error similar to below:
(gdb) run 
Starting program: a.out
Unable to find Mach task port for process-id 627: (os/kern) failure (0x5).
(please check gdb is codesigned - see taskgated(8))

The solution is as follows:
1. Restart OS X. Enter recovery mode by pressing and holding [command + R] until you see Apple logo. See here for more detail.

2. In the recovery mode, choose utilities menu and open up terminal

3. In the terminal, disable system integrity protection (SIP)
$ csrutil disable && reboot

4. Add -p option to /System/Library/LaunchDaemons/com.apple.taskgated.plist file. After your edit, it should read something like (line 22)
<array>
    <string>/usr/libexec/taskgated</string>
    <string>-sp</string>
</array>

5. (Optional) Re-enable SIP by repeating steps 1~3 with the command and reboot.
$ csrutil enable && reboot

6. Add your username to procmod group
$ sudo dseditgroup -o edit -a $USER -t user procmod

7. Locate gdb executable file and run
$ sudo chgrp procmod $(which gdb)
$ sudo chmod g+s $(which gdb)

Please be advised that you will need to reboot your system for the change to take effect.

Now, you should be able to use gdb on Mac OS X!


Saturday, April 23, 2016

How to Install Google Chrome Browser on Ubuntu 16.04 LTS

Trust me, it wasn't so easy to install Google Chrome on my freshly installed Ubuntu 16.04 LTS 64bit system. Let's see what I encountered, and let me share the solution.

First, I downloaded the chrome browser install file from https://www.google.com/chrome/browser/desktop/index.html

Next, I tried to install it
$ sudo dpkg -i google-chrome-stable_current_amd64.deb


I was getting the following error
Selecting previously unselected package google-chrome-stable.
(Reading database ... 191101 files and directories currently installed.)
Preparing to unpack google-chrome-stable_current_amd64.deb ...
Unpacking google-chrome-stable (50.0.2661.86-1) ...
dpkg: dependency problems prevent configuration of google-chrome-stable:
 google-chrome-stable depends on libappindicator1; however:
  Package libappindicator1 is not installed.

dpkg: error processing package google-chrome-stable (--install):
 dependency problems - leaving unconfigured
Processing triggers for man-db (2.7.5-1) ...
Processing triggers for gnome-menus (3.13.3-6ubuntu3) ...
Processing triggers for desktop-file-utils (0.22-1ubuntu5) ...
Processing triggers for bamfdaemon (0.5.3~bzr0+16.04.20160415-0ubuntu1) ...
Rebuilding /usr/share/applications/bamf-2.index...
Processing triggers for mime-support (3.59ubuntu1) ...
Errors were encountered while processing:
 google-chrome-stable

Well, I thought I just needed to install the necessary package:
$ sudo apt-get update && sudo apt-get install libappindicator1 -y

But then, this is what I got.
Reading package lists... Done
Building dependency tree       
Reading state information... Done
You might want to run 'apt-get -f install' to correct these:
The following packages have unmet dependencies:
 libappindicator1 : Depends: libindicator7 (>= 0.4.90) but it is not going to be installed
E: Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution).

OK, for some reason mentioned above, I couldn't do it, without forcing it. I wanted to find a way to resolve it without actually forcing it though. So, what should I do?

Well, you would probably try installing libindicator7 first, and that's exactly what I did.
$ sudo apt-get install -y libindicator7

Unfortunately, I kept getting the error
Reading package lists... Done
Building dependency tree       
Reading state information... Done
You might want to run 'apt-get -f install' to correct these:
The following packages have unmet dependencies:
 google-chrome-stable : Depends: libappindicator1 but it is not going to be installed
E: Unmet dependencies. Try 'apt-get -f install' with no packages (or specify a solution).

It turns out that, the solution was simple. First, undo installation attempt of Google Chrome by
$ sudo apt-get remove -y google-chrome-stable

Interestingly, google-chrome-stable was installed on the system even if it complained with the error above. 
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following packages will be REMOVED:
  google-chrome-stable
0 upgraded, 0 newly installed, 1 to remove and 0 not upgraded.
1 not fully installed or removed.
After this operation, 186 MB disk space will be freed.
Do you want to continue? [Y/n] 
(Reading database ... 174822 files and directories currently installed.)
Removing google-chrome-stable (50.0.2661.86-1) ...
Processing triggers for gnome-menus (3.13.3-6ubuntu3) ...
Processing triggers for desktop-file-utils (0.22-1ubuntu5) ...
Processing triggers for bamfdaemon (0.5.3~bzr0+16.04.20160415-0ubuntu1) ...
Rebuilding /usr/share/applications/bamf-2.index...
Processing triggers for mime-support (3.59ubuntu1) ...
Processing triggers for man-db (2.7.5-1) ...

After successfully removing google-chrome-stable from the system, you can now proceed with installing libappindicator1
$ sudo apt-get install -y libappindicator1

Now, this doesn't give me any error or complaint.
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following NEW packages will be installed:
  libappindicator1
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 18.8 kB of archives.
After this operation, 101 kB of additional disk space will be used.
Get:1 http://us.archive.ubuntu.com/ubuntu xenial/main amd64 libappindicator1 amd64 12.10.1+15.04.20141110-0ubuntu1 [18.8 kB]
Fetched 18.8 kB in 0s (29.4 kB/s)           
Selecting previously unselected package libappindicator1.
(Reading database ... 174721 files and directories currently installed.)
Preparing to unpack .../libappindicator1_12.10.1+15.04.20141110-0ubuntu1_amd64.deb ...
Unpacking libappindicator1 (12.10.1+15.04.20141110-0ubuntu1) ...
Setting up libappindicator1 (12.10.1+15.04.20141110-0ubuntu1) ...
Processing triggers for libc-bin (2.23-0ubuntu3) ...

Now, you may proceed with google-chrome-stable installation again
$ sudo dpkg -i google-chrome-stable

It will install with no problem:
Selecting previously unselected package google-chrome-stable.
(Reading database ... 174726 files and directories currently installed.)
Preparing to unpack google-chrome-stable_current_amd64.deb ...
Unpacking google-chrome-stable (50.0.2661.86-1) ...
Setting up google-chrome-stable (50.0.2661.86-1) ...
update-alternatives: using /usr/bin/google-chrome-stable to provide /usr/bin/x-www-browser (x-www-browser) in auto mode
update-alternatives: using /usr/bin/google-chrome-stable to provide /usr/bin/gnome-www-browser (gnome-www-browser) in auto mode
update-alternatives: using /usr/bin/google-chrome-stable to provide /usr/bin/google-chrome (google-chrome) in auto mode
Processing triggers for man-db (2.7.5-1) ...
Processing triggers for gnome-menus (3.13.3-6ubuntu3) ...
Processing triggers for desktop-file-utils (0.22-1ubuntu5) ...
Processing triggers for bamfdaemon (0.5.3~bzr0+16.04.20160415-0ubuntu1) ...
Rebuilding /usr/share/applications/bamf-2.index...
Processing triggers for mime-support (3.59ubuntu1) ...

So, the lesson today is, if you failed to install something, you may want to remove it before trying to resolve the issues, at least for Ubuntu 16.04 LTS!

EDIT: Please refer to more recent post for an alternative solution.

How to Compile OPENSSH from Sources in the Respository on Ubuntu 16.04 LTS

In this post, I will describe how to check out the most recent openssh sources from the git repository and compile.

First, let's install necessary packages,
$ sudo apt-get install -y git autoconf libssl-dev zlib1g-dev

To clone from the git repository,
$ git clone git://anongit.mindrot.org/openssh.git

Next, go into the directory and read the instruction.
$ cd openssh
$ less INSTALL

Now that you are familiar with the instruction, let's go on. Create the configure file
$ autoreconf

Create the build directory and enter
$ mkdir build && cd build

Configure
$ ../configure

Make
$ make -j 2

Here, I am utilizing two cores, so the number 2 after -j option, but if you have an quad-core processor, you may want to use -j 4 option instead.

That's it. Let's verify that it is successful.
$./ssh -V
$ ssh -V

The two should output different!

Friday, April 22, 2016

How to Change OwnCloud Admin Password

If you ever forget our owncloud admin password, here is how to reset it.

First, you must be able to login with root privilege user on the server. Here, I will ssh into the server.
$ ssh server_admin@server_ip_address

Note that server_admin is the username for the server system (Ubuntu in my case) and server_ip_address is the IP address of the server.

Once you are logged in, you need to run
$ sudo -u www-data php /var/www/html/owncloud/occ user:resetpassword owncloud_admin

Here, I am assuming that you followed my previous post, so owncloud folder path is /var/www/html/owncloud. Replace owncloud_admin with your owncloud admin username, whose password you want to reset.

That's it!

Thursday, April 21, 2016

How to Mount EXFAT partition on Ubuntu 16.04 LTS

To mount exfat partition on Ubuntu, simply install the necessary packages:
$ sudo apt-get install exfat-fuse exfat-utils

If you need to mount it from the command line, you could do
$ sudo mkdir /media/exfat
$ sudo mount -t exfat /dev/sdxx /media/exfat
where /dev/sdxx could be /dev/sda1 or /dev/sda2, or so on.

If you are not sure whether the exfat partition you are looking for is /dev/sda1 or /dev/sda2, then you could also run
$ sudo lsblk -o NAME,FSTYPE,SIZE,MOUNTPOINT,LABEL

This should do it!

How to Upgrade to Ubuntu 16.04 LTS from 14.04 LTS

Finally, the day has come. Ubuntu 16.04 LTS has been just released today. In this post, I will cover how to upgrade your two-years old system 14.04 LTS to the shin new 16.04 LTS.

First, verify that release upgrader is set to lts
$ cat /etc/update-manager/release-upgrades

The last line should read
Prompt=lts

Next, make sure that your system is up to date
$ sudo apt-get upgrade -y

Next, if you are using Ubuntu Desktop, run
$ sudo update-manager -d

If you are using Ubuntu Server, run
$ sudo do-release-upgrade -d

That's it!

Saturday, April 2, 2016

How to Use SUDO in Debian

If you are a long time Ubuntu user who wants to try out Debian for fun, like myself, you may encounter
$ sudo apt-get install vim
-bash: sudo: command not found

This is because by default Debian doesn't come with sudo package. What you will need to do then is to use su command
$ su
Password: [root password]

You should now be able to login as root. Let's install sudo package first
# apt-get install sudo -y

Looks all good. Let's log out root and try sudo again
# exit
exit
$ sudo apt-get install vim
[sudo] password for xxx:
xxx is not in the sudoers file.  This incident will be reported.

OK this is a bit scary. The incident has been logged to/var/spool/mail/xxx file.
Well, how do we then add a user to become a sudoer? First, login as root again and then you run the following
$ su
# adduser xxx sudo
where xxx is the username that you'd like to add to the sudo group.

When done, you will need to re-login with xxx in order for this to take effect. Let's just reboot the system.
# reboot

After the reboot, you should be able to now type in sudo command to do administrative tasks
$ sudo apt-get install vim

By the way, in case you are wondering how to disable local root login in Debian system, just like Ubuntu, this is what you'll need to run the following command as a sudo user
$ sudo passwd -dl root

To enable root account, you will need to
$ sudo passwd root

Friday, April 1, 2016

How to Record Function Calls Using GDB Automated Script

Probably one of the best ways to analyze new program source files is by looking at the function calls. In this post, I will discuss how to record the function flow from the main function using gdb. The credit goes to Juan M. Bello Rivas, and I found this from the link here.

From the link above, download the callgraph.tar.gz file and extract it..
$ wget http://web.archive.org/web/20090317091725/http://superadditive.com/software/callgraph.tar.gz
$ tar xfz callgraph.tar.gz
$ cd callgraph

You will need gawk to be able to successfully run it, so let's install if not already installed on your system.
$ sudo apt-get install -y gawk

Sometimes, it may be the case that your system has the original version of awk, which won't work with the callgraph script. You may need to replace awk with gawk in the file.
$ sed -i 's/awk/gawk/g' callgraph

OK, you are now ready to run the script. Let's first test it with the given test.c code.
$ gcc -g test.c

You should have a.out executable file. Let's run the script file. Before that, by the way, don't forget to enable execution flag.
$ chmod u+x callgraph
$ ./callgraph a.out

You should now see the following output
main foo (n=23)
foo bar (n=23)

This is very cool! Note that this script is probably suitable to work with only a small or medium size program, but this shall be still very useful!

In case the link will become dead in the future, I will copy the callgraph script file and test.c file below:
#!/bin/sh

  # Copyright (c) 2004-2007 Juan M. Bello Rivas <jmbr@superadditive.com>
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

prog_name="callgraph"

if [ $# -lt 1 ]; then
    echo "Usage: $prog_name EXECUTABLE [ARGS...]"
    echo
    echo "Example: $prog_name ~/bin/test-program foo 23"
    exit 1
fi

# Sanity checks.
FILE=$1

if [ ! -x $FILE ]; then
    echo "$prog_name: Unable to find executable '$FILE'"
    exit 1
fi

LANG="" gdb --eval-command=quit $FILE 2>&1 \
    | grep -E '(no\ debugging\ symbols\ found|not\ in\ executable\ format)' 2>&1 > /dev/null
if [ $? -eq 0 ]; then
    echo -n "$prog_name: Can't print call graph for '$FILE' because it's not a "
    echo "binary executable compiled with debugging symbols."
    exit 1;
fi

shift

# Set up temporary files.
TRACE="`mktemp -t $prog_name.XXXXXXXXXX`" || exit
GETFUNCS="`mktemp -t $prog_name.XXXXXXXXXX`" || exit
trap 'rm -f -- "$TRACE" "$GETFUNCS"' EXIT
trap 'trap - EXIT; rm -f -- "$TRACE" "$GETFUNCS"; exit 1' HUP INT QUIT TERM

# Take control of GDB and print call graph.
cat > $GETFUNCS <<EOF
set height 0
info functions
EOF

gdb --batch --command=$GETFUNCS $FILE 2>/dev/null | awk '
function get_func_name(str)
{
  split(str, part, "(");
  len = split(part[1], part, " ");
  len = split(part[len], part, "*");

  return part[len];
}

BEGIN {
  total = 0;
  print "set width 0";
  print "set height 0";
  print "set verbose off";
}

/[a-zA-Z_][a-zA-Z0-9_]*\(/ {
  fn = get_func_name($0);
  printf("break %s\n", fn);
  ++total;
}

END {
  for (i = 1; i <= total; i++) {
    print "commands", i;
    /* print "info args"; */
    print "backtrace 2";
    print "continue";
    print "end";
  }

  print "run"
}
' > $TRACE

gdb --batch --command=$TRACE --tty=/dev/null --args $FILE $@ 2>/dev/null | awk '
function get_callee(s)
{
  split(s, info, ",");
  split(info[2], fn, " ");
  callee = fn[1];

  return callee;
}

function get_params(s, n)
{
  split(s, par, n);
  split(par[2], par, " at ");
  sub(/ \(/, "(", par[1]);

  return par[1];
}

BEGIN {
  isrecord = 0;
  callee = "";
  caller = "*INITIAL*";
  params = "";
}

/^Breakpoint [0-9]+,/ {
  isrecord = 1;

  callee = get_callee($0);
  params = get_params($0, callee);
}

/^#1[ \t]+/ {
  if (isrecord)
    caller = $4;
}

/^$/ {
  if (isrecord && (caller != "*INITIAL*")) {
    printf("%s %s %s\n", caller, callee, params);
    callee = caller = params = "";
  }
}
'


Here is test.c file
#include <stdio.h>
#include <stdlib.h>

static void foo(int n);
static void bar(int n);
static void baz(int n);

int
main(int argc, char *argv[])
{
foo(23);

exit(EXIT_SUCCESS);
}

void 
foo(int n)
{
bar(n);
}

void
bar(int n)
{
baz(n);
}

void
baz(int n)
{
return;
}